@nixxie-cms/core 1.0.0 → 1.0.2
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/admin-ui/components/dist/nixxie-cms-core-admin-ui-components.cjs.js +4 -4
- package/admin-ui/components/dist/nixxie-cms-core-admin-ui-components.esm.js +4 -4
- package/admin-ui/context/dist/nixxie-cms-core-admin-ui-context.cjs.js +2 -2
- package/admin-ui/context/dist/nixxie-cms-core-admin-ui-context.esm.js +2 -2
- package/context/dist/nixxie-cms-core-context.cjs.js +2 -2
- package/context/dist/nixxie-cms-core-context.esm.js +2 -2
- package/dist/{CreateItemDialog-33335548.esm.js → CreateItemDialog-7008b050.esm.js} +1 -1
- package/dist/{CreateItemDialog-56cf59b7.cjs.js → CreateItemDialog-a0cab315.cjs.js} +1 -1
- package/dist/{PageContainer-7db73317.esm.js → PageContainer-5ae731cc.esm.js} +25 -18
- package/dist/{PageContainer-27c27f10.cjs.js → PageContainer-abd7159f.cjs.js} +25 -18
- package/dist/{admin-meta-graphql-6f7f5331.esm.js → admin-meta-graphql-0e6e606e.esm.js} +1 -1
- package/dist/{admin-meta-graphql-c8f926e9.cjs.js → admin-meta-graphql-306c224a.cjs.js} +1 -1
- package/dist/{context-3132c3ed.esm.js → context-af9957ed.esm.js} +2 -2
- package/dist/{context-e7a45152.cjs.js → context-b5204629.cjs.js} +2 -2
- package/dist/declarations/src/admin-ui/components/Navigation.d.ts.map +1 -1
- package/dist/declarations/src/admin-ui/components/PageContainer.d.ts.map +1 -1
- package/dist/declarations/src/helpers.d.ts.map +1 -1
- package/dist/declarations/src/index.d.ts +1 -0
- package/dist/declarations/src/index.d.ts.map +1 -1
- package/dist/declarations/src/internal-unstable/admin-ui/id-field-view.d.ts.map +1 -0
- package/dist/declarations/src/internal-unstable/admin-ui/pages/App/index.d.ts.map +1 -0
- package/dist/declarations/src/internal-unstable/admin-ui/pages/CreateItemPage/index.d.ts.map +1 -0
- package/dist/declarations/src/internal-unstable/admin-ui/pages/HomePage/index.d.ts.map +1 -0
- package/dist/declarations/src/internal-unstable/admin-ui/pages/ItemPage/index.d.ts.map +1 -0
- package/dist/declarations/src/internal-unstable/admin-ui/pages/ListPage/index.d.ts.map +1 -0
- package/dist/declarations/src/internal-unstable/admin-ui/pages/NoAccessPage/index.d.ts.map +1 -0
- package/dist/declarations/src/internal-unstable/artifacts.d.ts.map +1 -0
- package/dist/declarations/src/lib/core/initialise-lists.d.ts +1 -1
- package/dist/declarations/src/schema.d.ts.map +1 -1
- package/dist/declarations/src/types/config/index.d.ts +60 -1
- package/dist/declarations/src/types/config/index.d.ts.map +1 -1
- package/dist/declarations/src/types/config/lists.d.ts +4 -4
- package/dist/declarations/src/types/context.d.ts +150 -0
- package/dist/declarations/src/types/context.d.ts.map +1 -1
- package/dist/declarations/src/types/next-fields.d.ts +1 -1
- package/dist/{express-e9ed9a7d.cjs.js → express-455ae20c.cjs.js} +1 -1
- package/dist/{express-6743b918.esm.js → express-7559ca2d.esm.js} +1 -1
- package/dist/{index-ac01583b.cjs.js → index-89635494.cjs.js} +4 -4
- package/dist/{index-24b78415.esm.js → index-baa799e0.esm.js} +4 -4
- package/dist/nixxie-cms-core.cjs.js +104 -77
- package/dist/nixxie-cms-core.esm.js +104 -77
- package/dist/{non-null-graphql-5315718c.esm.js → non-null-graphql-a84ed64d.esm.js} +1 -1
- package/dist/{non-null-graphql-17b83ddc.cjs.js → non-null-graphql-add6bb3d.cjs.js} +1 -1
- package/dist/{resolve-hooks-66fe8a8e.cjs.js → resolve-hooks-165a9ce2.cjs.js} +1 -1
- package/dist/{resolve-hooks-17aafd37.esm.js → resolve-hooks-6813a045.esm.js} +2 -2
- package/dist/{system-dfec2f0a.esm.js → system-03e49e4f.esm.js} +8 -4
- package/dist/{system-48c5f6df.cjs.js → system-a321642d.cjs.js} +8 -4
- package/dist/{useFilter-0b5a1ee6.esm.js → useFilter-9b6db1f9.esm.js} +1 -1
- package/dist/{useFilter-1a4e6900.cjs.js → useFilter-acc9d413.cjs.js} +1 -1
- package/fields/dist/nixxie-cms-core-fields.cjs.js +16 -16
- package/fields/dist/nixxie-cms-core-fields.esm.js +17 -17
- package/fields/types/bytes/dist/nixxie-cms-core-fields-types-bytes.cjs.js +3 -3
- package/fields/types/bytes/dist/nixxie-cms-core-fields-types-bytes.esm.js +3 -3
- package/fields/types/bytes/views/dist/nixxie-cms-core-fields-types-bytes-views.cjs.js +1 -1
- package/fields/types/bytes/views/dist/nixxie-cms-core-fields-types-bytes-views.esm.js +1 -1
- package/fields/types/password/dist/nixxie-cms-core-fields-types-password.cjs.js +3 -3
- package/fields/types/password/dist/nixxie-cms-core-fields-types-password.esm.js +3 -3
- package/fields/types/relationship/views/dist/nixxie-cms-core-fields-types-relationship-views.cjs.js +4 -4
- package/fields/types/relationship/views/dist/nixxie-cms-core-fields-types-relationship-views.esm.js +4 -4
- package/fields/types/select/views/dist/nixxie-cms-core-fields-types-select-views.cjs.js +1 -1
- package/fields/types/select/views/dist/nixxie-cms-core-fields-types-select-views.esm.js +1 -1
- package/fields/types/text/views/dist/nixxie-cms-core-fields-types-text-views.cjs.js +1 -1
- package/fields/types/text/views/dist/nixxie-cms-core-fields-types-text-views.esm.js +1 -1
- package/internal-unstable/admin-ui/id-field-view/dist/nixxie-cms-core-internal-unstable-admin-ui-id-field-view.cjs.d.ts +2 -0
- package/internal-unstable/admin-ui/id-field-view/dist/nixxie-cms-core-internal-unstable-admin-ui-id-field-view.cjs.js +244 -0
- package/internal-unstable/admin-ui/id-field-view/dist/nixxie-cms-core-internal-unstable-admin-ui-id-field-view.esm.js +235 -0
- package/internal-unstable/admin-ui/id-field-view/package.json +4 -0
- package/internal-unstable/admin-ui/next-config/package.json +4 -0
- package/internal-unstable/admin-ui/pages/App/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-App.cjs.d.ts +2 -0
- package/internal-unstable/admin-ui/pages/App/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-App.cjs.js +59 -0
- package/internal-unstable/admin-ui/pages/App/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-App.esm.js +55 -0
- package/internal-unstable/admin-ui/pages/App/package.json +4 -0
- package/internal-unstable/admin-ui/pages/CreateItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-CreateItemPage.cjs.d.ts +2 -0
- package/internal-unstable/admin-ui/pages/CreateItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-CreateItemPage.cjs.js +116 -0
- package/internal-unstable/admin-ui/pages/CreateItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-CreateItemPage.esm.js +112 -0
- package/internal-unstable/admin-ui/pages/CreateItemPage/package.json +4 -0
- package/internal-unstable/admin-ui/pages/HomePage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-HomePage.cjs.d.ts +2 -0
- package/internal-unstable/admin-ui/pages/HomePage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-HomePage.cjs.js +336 -0
- package/internal-unstable/admin-ui/pages/HomePage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-HomePage.esm.js +332 -0
- package/internal-unstable/admin-ui/pages/HomePage/package.json +4 -0
- package/internal-unstable/admin-ui/pages/ItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ItemPage.cjs.d.ts +2 -0
- package/internal-unstable/admin-ui/pages/ItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ItemPage.cjs.js +463 -0
- package/internal-unstable/admin-ui/pages/ItemPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ItemPage.esm.js +455 -0
- package/internal-unstable/admin-ui/pages/ItemPage/package.json +4 -0
- package/internal-unstable/admin-ui/pages/ListPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ListPage.cjs.d.ts +2 -0
- package/internal-unstable/admin-ui/pages/ListPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ListPage.cjs.js +1195 -0
- package/internal-unstable/admin-ui/pages/ListPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-ListPage.esm.js +1187 -0
- package/internal-unstable/admin-ui/pages/ListPage/package.json +4 -0
- package/internal-unstable/admin-ui/pages/NoAccessPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-NoAccessPage.cjs.d.ts +2 -0
- package/internal-unstable/admin-ui/pages/NoAccessPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-NoAccessPage.cjs.js +40 -0
- package/internal-unstable/admin-ui/pages/NoAccessPage/dist/nixxie-cms-core-internal-unstable-admin-ui-pages-NoAccessPage.esm.js +35 -0
- package/internal-unstable/admin-ui/pages/NoAccessPage/package.json +4 -0
- package/internal-unstable/artifacts/dist/nixxie-cms-core-internal-unstable-artifacts.cjs.d.ts +2 -0
- package/internal-unstable/artifacts/dist/nixxie-cms-core-internal-unstable-artifacts.cjs.js +51 -0
- package/internal-unstable/artifacts/dist/nixxie-cms-core-internal-unstable-artifacts.esm.js +38 -0
- package/internal-unstable/artifacts/package.json +4 -0
- package/package.json +44 -44
- package/scripts/cli/dist/nixxie-cms-core-scripts-cli.cjs.js +44 -15
- package/scripts/cli/dist/nixxie-cms-core-scripts-cli.esm.js +44 -15
- package/scripts/dist/nixxie-cms-core-scripts.cjs.js +3 -3
- package/scripts/dist/nixxie-cms-core-scripts.esm.js +3 -3
- package/src/admin-ui/admin-meta-graphql.ts +168 -168
- package/src/admin-ui/components/CommandPalette.tsx +433 -431
- package/src/admin-ui/components/Navigation.tsx +389 -385
- package/src/admin-ui/components/PageContainer.tsx +311 -310
- package/src/admin-ui/components/WelcomeDialog.tsx +1 -1
- package/src/admin-ui/context.tsx +338 -338
- package/src/admin-ui/templates/app.ts +60 -60
- package/src/admin-ui/templates/create-item.ts +5 -5
- package/src/admin-ui/templates/home.ts +2 -2
- package/src/admin-ui/templates/item.tsx +5 -5
- package/src/admin-ui/templates/list.tsx +5 -5
- package/src/admin-ui/templates/next-config.ts +29 -0
- package/src/admin-ui/templates/no-access.ts +7 -7
- package/src/fields/types/bigInt/index.ts +181 -181
- package/src/fields/types/bytes/index.ts +275 -275
- package/src/fields/types/calendarDay/index.ts +194 -194
- package/src/fields/types/checkbox/index.ts +76 -76
- package/src/fields/types/decimal/index.ts +182 -182
- package/src/fields/types/file/index.ts +168 -168
- package/src/fields/types/float/index.ts +133 -133
- package/src/fields/types/image/index.ts +244 -244
- package/src/fields/types/integer/index.ts +156 -156
- package/src/fields/types/json/index.ts +77 -77
- package/src/fields/types/multiselect/index.ts +212 -212
- package/src/fields/types/password/index.ts +241 -241
- package/src/fields/types/relationship/index.ts +381 -381
- package/src/fields/types/relationship/views/RelationshipTable.tsx +190 -190
- package/src/fields/types/select/index.ts +226 -226
- package/src/fields/types/text/index.ts +207 -207
- package/src/fields/types/timestamp/index.ts +116 -116
- package/src/fields/types/virtual/index.ts +108 -108
- package/src/helpers.ts +342 -316
- package/src/index.ts +4 -0
- package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/id-field-view.tsx +167 -167
- package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/App/index.tsx +22 -22
- package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/CreateItemPage/index.tsx +71 -71
- package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/HomePage/index.tsx +333 -333
- package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ItemPage/common.tsx +358 -358
- package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ItemPage/index.tsx +483 -483
- package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ListPage/FilterAdd.tsx +221 -221
- package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ListPage/PaginationControls.tsx +170 -170
- package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ListPage/Tag.tsx +72 -72
- package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ListPage/index.tsx +1006 -1006
- package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/NoAccessPage/index.tsx +24 -24
- package/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/artifacts.ts +5 -5
- package/src/lib/context/createContext.ts +165 -161
- package/src/lib/core/initialise-lists.ts +1097 -1097
- package/src/lib/id-field.ts +214 -214
- package/src/lib/telemetry.ts +342 -342
- package/src/schema.ts +237 -233
- package/src/scripts/telemetry.ts +1 -1
- package/src/types/config/index.ts +400 -333
- package/src/types/config/lists.ts +4 -4
- package/src/types/context.ts +700 -530
- package/src/types/next-fields.ts +499 -499
- package/src/types/telemetry.ts +51 -51
- package/tests/telemetry.test.ts +361 -361
- package/CHANGELOG.md +0 -3158
- package/___internal-do-not-use-will-break-in-patch/admin-ui/id-field-view/package.json +0 -4
- package/___internal-do-not-use-will-break-in-patch/admin-ui/next-config/package.json +0 -4
- package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/App/package.json +0 -4
- package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/CreateItemPage/package.json +0 -4
- package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/HomePage/package.json +0 -4
- package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage/package.json +0 -4
- package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage/package.json +0 -4
- package/___internal-do-not-use-will-break-in-patch/admin-ui/pages/NoAccessPage/package.json +0 -4
- package/___internal-do-not-use-will-break-in-patch/artifacts/package.json +0 -4
- package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/id-field-view.d.ts.map +0 -1
- package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/App/index.d.ts.map +0 -1
- package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/CreateItemPage/index.d.ts.map +0 -1
- package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/HomePage/index.d.ts.map +0 -1
- package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ItemPage/index.d.ts.map +0 -1
- package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/ListPage/index.d.ts.map +0 -1
- package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/admin-ui/pages/NoAccessPage/index.d.ts.map +0 -1
- package/dist/declarations/src/___internal-do-not-use-will-break-in-patch/artifacts.d.ts.map +0 -1
- /package/dist/{common-1a350e11.cjs.js → common-5933f758.cjs.js} +0 -0
- /package/dist/{common-29fc82e6.esm.js → common-ea5c441a.esm.js} +0 -0
- /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/id-field-view.d.ts +0 -0
- /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/App/index.d.ts +0 -0
- /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/CreateItemPage/index.d.ts +0 -0
- /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/HomePage/index.d.ts +0 -0
- /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ItemPage/index.d.ts +0 -0
- /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/ListPage/index.d.ts +0 -0
- /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/admin-ui/pages/NoAccessPage/index.d.ts +0 -0
- /package/dist/declarations/src/{___internal-do-not-use-will-break-in-patch → internal-unstable}/artifacts.d.ts +0 -0
package/src/lib/telemetry.ts
CHANGED
|
@@ -1,342 +1,342 @@
|
|
|
1
|
-
import { platform } from 'node:os'
|
|
2
|
-
import https from 'node:https'
|
|
3
|
-
|
|
4
|
-
import ci from 'ci-info'
|
|
5
|
-
import Conf from 'conf'
|
|
6
|
-
import { bold, blue as b, yellow as y, red as r, green as g, grey } from 'chalk'
|
|
7
|
-
import type { Device, Project, TelemetryVersion1, TelemetryVersion2 } from '../types/telemetry'
|
|
8
|
-
import type { DatabaseProvider } from '../types'
|
|
9
|
-
import type { InitialisedList } from './core/initialise-lists'
|
|
10
|
-
|
|
11
|
-
const defaultTelemetryEndpoint = 'https://telemetry.
|
|
12
|
-
|
|
13
|
-
function log(message: unknown) {
|
|
14
|
-
if (process.env.
|
|
15
|
-
console.log(`${message}`)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
type Telemetry = TelemetryVersion2
|
|
20
|
-
type TelemetryOK = Exclude<Telemetry, false | undefined>
|
|
21
|
-
type Configuration = ReturnType<typeof getTelemetryConfig>['userConfig']
|
|
22
|
-
|
|
23
|
-
function getTelemetryConfig() {
|
|
24
|
-
const userConfig = new Conf<{
|
|
25
|
-
telemetry?: TelemetryVersion2
|
|
26
|
-
}>({
|
|
27
|
-
projectName: 'nixxiecms',
|
|
28
|
-
projectSuffix: '',
|
|
29
|
-
projectVersion: '3.0.0',
|
|
30
|
-
migrations: {
|
|
31
|
-
'^2.0.0': store => {
|
|
32
|
-
const existing = store.get('telemetry') as TelemetryVersion1
|
|
33
|
-
if (!existing) return // skip non-configured or known opt-outs
|
|
34
|
-
|
|
35
|
-
const replacement: TelemetryVersion2 = {
|
|
36
|
-
informedAt: null, // re-inform
|
|
37
|
-
device: {
|
|
38
|
-
lastSentDate: existing.device.lastSentDate ?? null,
|
|
39
|
-
},
|
|
40
|
-
projects: {}, // see below
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// copy existing project.lastSentDate's
|
|
44
|
-
for (const [projectPath, project] of Object.entries(existing.projects)) {
|
|
45
|
-
if (projectPath === 'default') continue // informedAt moved to device.lastSentDate
|
|
46
|
-
|
|
47
|
-
// dont copy garbage
|
|
48
|
-
if (typeof project !== 'object') continue
|
|
49
|
-
if (typeof project.lastSentDate !== 'string') continue
|
|
50
|
-
if (new Date(project.lastSentDate).toString() === 'Invalid Date') continue
|
|
51
|
-
|
|
52
|
-
// retain lastSentDate
|
|
53
|
-
replacement.projects[projectPath] = {
|
|
54
|
-
lastSentDate: project.lastSentDate,
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
store.set('telemetry', replacement satisfies TelemetryVersion2)
|
|
59
|
-
},
|
|
60
|
-
'^3.0.0': store => {
|
|
61
|
-
const existing = store.get('telemetry') as TelemetryVersion2
|
|
62
|
-
if (!existing) return // skip non-configured or known opt-outs
|
|
63
|
-
|
|
64
|
-
store.set('telemetry', {
|
|
65
|
-
...existing,
|
|
66
|
-
informedAt: null, // re-inform
|
|
67
|
-
} satisfies Telemetry)
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
telemetry: userConfig.get('telemetry'),
|
|
74
|
-
userConfig,
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function getDefault(telemetry: Telemetry) {
|
|
79
|
-
if (telemetry) return telemetry
|
|
80
|
-
return {
|
|
81
|
-
informedAt: null,
|
|
82
|
-
device: {
|
|
83
|
-
lastSentDate: null,
|
|
84
|
-
},
|
|
85
|
-
projects: {},
|
|
86
|
-
} satisfies Telemetry // help Typescript infer the type
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const todaysDate = new Date().toISOString().slice(0, 10)
|
|
90
|
-
|
|
91
|
-
function collectFieldCount(lists: Record<string, InitialisedList>) {
|
|
92
|
-
const fields: Project['fields'] = { unknown: 0 }
|
|
93
|
-
|
|
94
|
-
for (const list of Object.values(lists)) {
|
|
95
|
-
for (const [fieldPath, field] of Object.entries(list.fields)) {
|
|
96
|
-
const fieldType = field.
|
|
97
|
-
if (!fieldType) {
|
|
98
|
-
// skip id fields
|
|
99
|
-
if (fieldPath.endsWith('id')) continue
|
|
100
|
-
fields.unknown++
|
|
101
|
-
continue
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
fields[fieldType] ||= 0
|
|
105
|
-
fields[fieldType] += 1
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return fields
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async function collectPackageVersions() {
|
|
113
|
-
const packages: Project['packages'] = {
|
|
114
|
-
'@nixxie-cms/core': '0.0.0', // "unknown"
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
for (const packageName of [
|
|
118
|
-
'@nixxie-cms/core',
|
|
119
|
-
'@nixxie-cms/auth',
|
|
120
|
-
'@nixxie-cms/fields-document',
|
|
121
|
-
'@nixxie-cms/cloudinary',
|
|
122
|
-
'@nixxie-cms/session-store-redis', // we hope usage to drops to zero
|
|
123
|
-
'@opensaas/nixxie-nextjs-auth',
|
|
124
|
-
]) {
|
|
125
|
-
try {
|
|
126
|
-
const packageJson = require(`${packageName}/package.json`)
|
|
127
|
-
// const packageJson = await import(`${packageName}/package.json`, { assert: { type: 'json' } }) // TODO: broken in jest
|
|
128
|
-
packages[packageName] = packageJson.version
|
|
129
|
-
} catch (err) {
|
|
130
|
-
// do nothing, the package is probably not installed
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return packages
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function printNext(telemetry: Telemetry) {
|
|
138
|
-
if (!telemetry) {
|
|
139
|
-
console.log(`Telemetry data will ${r`not`} be sent by this system user`)
|
|
140
|
-
return
|
|
141
|
-
}
|
|
142
|
-
console.log(`Telemetry data will be sent the next time you run ${g`"nixxie dev"`}`)
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function printTelemetryStatus(telemetry: Telemetry, updated = false) {
|
|
146
|
-
const auxverb = updated ? 'has been' : 'is'
|
|
147
|
-
|
|
148
|
-
if (telemetry === undefined) {
|
|
149
|
-
console.log(`Nixxie telemetry ${auxverb} ${y`uninitialized`}`)
|
|
150
|
-
console.log()
|
|
151
|
-
printNext(telemetry)
|
|
152
|
-
return
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (telemetry === false) {
|
|
156
|
-
console.log(`Nixxie telemetry ${auxverb} ${r`disabled`}`)
|
|
157
|
-
console.log()
|
|
158
|
-
printNext(telemetry)
|
|
159
|
-
return
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
console.log(`Nixxie telemetry ${auxverb} ${g`enabled`}`)
|
|
163
|
-
console.log()
|
|
164
|
-
|
|
165
|
-
console.log(` Device telemetry was last sent on ${telemetry.device.lastSentDate}`)
|
|
166
|
-
for (const [projectPath, project] of Object.entries(telemetry.projects)) {
|
|
167
|
-
console.log(
|
|
168
|
-
` Project telemetry for "${y(projectPath)}" was last sent on ${project?.lastSentDate}`
|
|
169
|
-
)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
console.log()
|
|
173
|
-
printNext(telemetry)
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function inform(telemetry: TelemetryOK, userConfig: Configuration) {
|
|
177
|
-
console.log() // gap to help visiblity
|
|
178
|
-
console.log(`${bold('Nixxie Telemetry')}`)
|
|
179
|
-
console.log(`${y`Nixxie collects anonymous data when you run`} ${g`"nixxie dev"`}`)
|
|
180
|
-
console.log(
|
|
181
|
-
`You can use ${g`"nixxie telemetry --help"`} to update your preferences at any time`
|
|
182
|
-
)
|
|
183
|
-
if (telemetry.informedAt === null) {
|
|
184
|
-
console.log()
|
|
185
|
-
console.log(`No telemetry data has been sent as part of this notice`)
|
|
186
|
-
}
|
|
187
|
-
console.log()
|
|
188
|
-
printNext(telemetry)
|
|
189
|
-
console.log() // gap to help visiblity
|
|
190
|
-
console.log(
|
|
191
|
-
`For more information, including how to opt-out see ${grey`https://
|
|
192
|
-
)
|
|
193
|
-
|
|
194
|
-
// update the informedAt
|
|
195
|
-
telemetry.informedAt = new Date().toJSON()
|
|
196
|
-
userConfig.set('telemetry', telemetry)
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
async function sendEvent(eventType: 'project', eventData: Project): Promise<void>
|
|
200
|
-
async function sendEvent(eventType: 'device', eventData: Device): Promise<void>
|
|
201
|
-
async function sendEvent(eventType: 'project' | 'device', eventData: Project | Device) {
|
|
202
|
-
const endpoint = process.env.
|
|
203
|
-
await new Promise<void>(resolve => {
|
|
204
|
-
const req = https.request(
|
|
205
|
-
`${endpoint}${eventType}`,
|
|
206
|
-
{
|
|
207
|
-
method: 'POST',
|
|
208
|
-
headers: {
|
|
209
|
-
'Content-Type': 'application/json',
|
|
210
|
-
},
|
|
211
|
-
},
|
|
212
|
-
() => resolve()
|
|
213
|
-
)
|
|
214
|
-
|
|
215
|
-
req.once('error', err => {
|
|
216
|
-
log(err?.message ?? err)
|
|
217
|
-
resolve()
|
|
218
|
-
})
|
|
219
|
-
req.end(JSON.stringify(eventData))
|
|
220
|
-
})
|
|
221
|
-
|
|
222
|
-
log(`sent ${eventType} report`)
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
async function sendProjectTelemetryEvent(
|
|
226
|
-
cwd: string,
|
|
227
|
-
lists: Record<string, InitialisedList>,
|
|
228
|
-
dbProviderName: DatabaseProvider,
|
|
229
|
-
telemetry: TelemetryOK,
|
|
230
|
-
userConfig: Configuration
|
|
231
|
-
) {
|
|
232
|
-
const project = telemetry.projects[cwd] ?? { lastSentDate: null }
|
|
233
|
-
const { lastSentDate } = project
|
|
234
|
-
if (lastSentDate && lastSentDate === todaysDate) {
|
|
235
|
-
log('project telemetry already sent today')
|
|
236
|
-
return
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
await sendEvent('project', {
|
|
240
|
-
lastSentDate,
|
|
241
|
-
packages: await collectPackageVersions(),
|
|
242
|
-
database: dbProviderName,
|
|
243
|
-
lists: Object.keys(lists).length,
|
|
244
|
-
fields: collectFieldCount(lists),
|
|
245
|
-
})
|
|
246
|
-
|
|
247
|
-
// update the project lastSentDate
|
|
248
|
-
telemetry.projects[cwd] = { lastSentDate: todaysDate }
|
|
249
|
-
userConfig.set('telemetry', telemetry)
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
async function sendDeviceTelemetryEvent(telemetry: TelemetryOK, userConfig: Configuration) {
|
|
253
|
-
const { lastSentDate } = telemetry.device
|
|
254
|
-
if (lastSentDate && lastSentDate === todaysDate) {
|
|
255
|
-
log('device telemetry already sent today')
|
|
256
|
-
return
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
await sendEvent('device', {
|
|
260
|
-
lastSentDate,
|
|
261
|
-
os: platform(),
|
|
262
|
-
node: process.versions.node.split('.')[0],
|
|
263
|
-
})
|
|
264
|
-
|
|
265
|
-
// update the device lastSentDate
|
|
266
|
-
telemetry.device = { lastSentDate: todaysDate }
|
|
267
|
-
userConfig.set('telemetry', telemetry)
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
export async function runTelemetry(
|
|
271
|
-
cwd: string,
|
|
272
|
-
lists: Record<string, InitialisedList>,
|
|
273
|
-
dbProviderName: DatabaseProvider
|
|
274
|
-
) {
|
|
275
|
-
try {
|
|
276
|
-
if (ci.isCI) {
|
|
277
|
-
console.log(`Nixxie Telemetry is ${r`disabled`} (running in CI)`)
|
|
278
|
-
return
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
const { telemetry, userConfig } = getTelemetryConfig()
|
|
282
|
-
if (telemetry === false) {
|
|
283
|
-
console.log(`Nixxie Telemetry is ${r`disabled`} (via opt-out)`)
|
|
284
|
-
return
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
if (process.env.NIXXIE_TELEMETRY_DISABLED === '1') {
|
|
288
|
-
console.log(`Nixxie Telemetry is ${r`disabled`} (NIXXIE_TELEMETRY_DISABLED is set)`)
|
|
289
|
-
return
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
if (process.env.DO_NOT_TRACK === '1') {
|
|
293
|
-
console.log(`Nixxie Telemetry is ${r`disabled`} (DO_NOT_TRACK is set)`)
|
|
294
|
-
return
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (process.env.NODE_ENV === 'production') {
|
|
298
|
-
console.log(`Nixxie Telemetry is ${r`disabled`} (NODE_ENV is production)`)
|
|
299
|
-
return
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// don't send telemetry before we inform the user, allowing opt-out
|
|
303
|
-
const telemetryDefaulted = getDefault(telemetry)
|
|
304
|
-
if (!telemetryDefaulted.informedAt) return inform(telemetryDefaulted, userConfig)
|
|
305
|
-
|
|
306
|
-
console.log(`Nixxie Telemetry is ${g`enabled`}`)
|
|
307
|
-
|
|
308
|
-
await sendProjectTelemetryEvent(cwd, lists, dbProviderName, telemetryDefaulted, userConfig)
|
|
309
|
-
await sendDeviceTelemetryEvent(telemetryDefaulted, userConfig)
|
|
310
|
-
} catch (err: any) {
|
|
311
|
-
log(err?.message ?? err)
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
export function statusTelemetry(updated = false) {
|
|
315
|
-
const { telemetry } = getTelemetryConfig()
|
|
316
|
-
printTelemetryStatus(telemetry, updated)
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
export function informTelemetry() {
|
|
320
|
-
const { userConfig } = getTelemetryConfig()
|
|
321
|
-
inform(getDefault(false), userConfig)
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
export function enableTelemetry() {
|
|
325
|
-
const { telemetry, userConfig } = getTelemetryConfig()
|
|
326
|
-
if (!telemetry) {
|
|
327
|
-
userConfig.set('telemetry', getDefault(telemetry))
|
|
328
|
-
}
|
|
329
|
-
statusTelemetry(true)
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
export function disableTelemetry() {
|
|
333
|
-
const { userConfig } = getTelemetryConfig()
|
|
334
|
-
userConfig.set('telemetry', false)
|
|
335
|
-
statusTelemetry(true)
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
export function resetTelemetry() {
|
|
339
|
-
const { userConfig } = getTelemetryConfig()
|
|
340
|
-
userConfig.delete('telemetry')
|
|
341
|
-
statusTelemetry(true)
|
|
342
|
-
}
|
|
1
|
+
import { platform } from 'node:os'
|
|
2
|
+
import https from 'node:https'
|
|
3
|
+
|
|
4
|
+
import ci from 'ci-info'
|
|
5
|
+
import Conf from 'conf'
|
|
6
|
+
import { bold, blue as b, yellow as y, red as r, green as g, grey } from 'chalk'
|
|
7
|
+
import type { Device, Project, TelemetryVersion1, TelemetryVersion2 } from '../types/telemetry'
|
|
8
|
+
import type { DatabaseProvider } from '../types'
|
|
9
|
+
import type { InitialisedList } from './core/initialise-lists'
|
|
10
|
+
|
|
11
|
+
const defaultTelemetryEndpoint = 'https://telemetry.nixxieinternational.com/3/'
|
|
12
|
+
|
|
13
|
+
function log(message: unknown) {
|
|
14
|
+
if (process.env.NIXXIE_TELEMETRY_DEBUG === '1') {
|
|
15
|
+
console.log(`${message}`)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type Telemetry = TelemetryVersion2
|
|
20
|
+
type TelemetryOK = Exclude<Telemetry, false | undefined>
|
|
21
|
+
type Configuration = ReturnType<typeof getTelemetryConfig>['userConfig']
|
|
22
|
+
|
|
23
|
+
function getTelemetryConfig() {
|
|
24
|
+
const userConfig = new Conf<{
|
|
25
|
+
telemetry?: TelemetryVersion2
|
|
26
|
+
}>({
|
|
27
|
+
projectName: 'nixxiecms',
|
|
28
|
+
projectSuffix: '',
|
|
29
|
+
projectVersion: '3.0.0',
|
|
30
|
+
migrations: {
|
|
31
|
+
'^2.0.0': store => {
|
|
32
|
+
const existing = store.get('telemetry') as TelemetryVersion1
|
|
33
|
+
if (!existing) return // skip non-configured or known opt-outs
|
|
34
|
+
|
|
35
|
+
const replacement: TelemetryVersion2 = {
|
|
36
|
+
informedAt: null, // re-inform
|
|
37
|
+
device: {
|
|
38
|
+
lastSentDate: existing.device.lastSentDate ?? null,
|
|
39
|
+
},
|
|
40
|
+
projects: {}, // see below
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// copy existing project.lastSentDate's
|
|
44
|
+
for (const [projectPath, project] of Object.entries(existing.projects)) {
|
|
45
|
+
if (projectPath === 'default') continue // informedAt moved to device.lastSentDate
|
|
46
|
+
|
|
47
|
+
// dont copy garbage
|
|
48
|
+
if (typeof project !== 'object') continue
|
|
49
|
+
if (typeof project.lastSentDate !== 'string') continue
|
|
50
|
+
if (new Date(project.lastSentDate).toString() === 'Invalid Date') continue
|
|
51
|
+
|
|
52
|
+
// retain lastSentDate
|
|
53
|
+
replacement.projects[projectPath] = {
|
|
54
|
+
lastSentDate: project.lastSentDate,
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
store.set('telemetry', replacement satisfies TelemetryVersion2)
|
|
59
|
+
},
|
|
60
|
+
'^3.0.0': store => {
|
|
61
|
+
const existing = store.get('telemetry') as TelemetryVersion2
|
|
62
|
+
if (!existing) return // skip non-configured or known opt-outs
|
|
63
|
+
|
|
64
|
+
store.set('telemetry', {
|
|
65
|
+
...existing,
|
|
66
|
+
informedAt: null, // re-inform
|
|
67
|
+
} satisfies Telemetry)
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
telemetry: userConfig.get('telemetry'),
|
|
74
|
+
userConfig,
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function getDefault(telemetry: Telemetry) {
|
|
79
|
+
if (telemetry) return telemetry
|
|
80
|
+
return {
|
|
81
|
+
informedAt: null,
|
|
82
|
+
device: {
|
|
83
|
+
lastSentDate: null,
|
|
84
|
+
},
|
|
85
|
+
projects: {},
|
|
86
|
+
} satisfies Telemetry // help Typescript infer the type
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const todaysDate = new Date().toISOString().slice(0, 10)
|
|
90
|
+
|
|
91
|
+
function collectFieldCount(lists: Record<string, InitialisedList>) {
|
|
92
|
+
const fields: Project['fields'] = { unknown: 0 }
|
|
93
|
+
|
|
94
|
+
for (const list of Object.values(lists)) {
|
|
95
|
+
for (const [fieldPath, field] of Object.entries(list.fields)) {
|
|
96
|
+
const fieldType = field.__nxTelemetryFieldTypeName
|
|
97
|
+
if (!fieldType) {
|
|
98
|
+
// skip id fields
|
|
99
|
+
if (fieldPath.endsWith('id')) continue
|
|
100
|
+
fields.unknown++
|
|
101
|
+
continue
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
fields[fieldType] ||= 0
|
|
105
|
+
fields[fieldType] += 1
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return fields
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function collectPackageVersions() {
|
|
113
|
+
const packages: Project['packages'] = {
|
|
114
|
+
'@nixxie-cms/core': '0.0.0', // "unknown"
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
for (const packageName of [
|
|
118
|
+
'@nixxie-cms/core',
|
|
119
|
+
'@nixxie-cms/auth',
|
|
120
|
+
'@nixxie-cms/fields-document',
|
|
121
|
+
'@nixxie-cms/cloudinary',
|
|
122
|
+
'@nixxie-cms/session-store-redis', // we hope usage to drops to zero
|
|
123
|
+
'@opensaas/nixxie-nextjs-auth',
|
|
124
|
+
]) {
|
|
125
|
+
try {
|
|
126
|
+
const packageJson = require(`${packageName}/package.json`)
|
|
127
|
+
// const packageJson = await import(`${packageName}/package.json`, { assert: { type: 'json' } }) // TODO: broken in jest
|
|
128
|
+
packages[packageName] = packageJson.version
|
|
129
|
+
} catch (err) {
|
|
130
|
+
// do nothing, the package is probably not installed
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return packages
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function printNext(telemetry: Telemetry) {
|
|
138
|
+
if (!telemetry) {
|
|
139
|
+
console.log(`Telemetry data will ${r`not`} be sent by this system user`)
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
console.log(`Telemetry data will be sent the next time you run ${g`"nixxie dev"`}`)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function printTelemetryStatus(telemetry: Telemetry, updated = false) {
|
|
146
|
+
const auxverb = updated ? 'has been' : 'is'
|
|
147
|
+
|
|
148
|
+
if (telemetry === undefined) {
|
|
149
|
+
console.log(`Nixxie telemetry ${auxverb} ${y`uninitialized`}`)
|
|
150
|
+
console.log()
|
|
151
|
+
printNext(telemetry)
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (telemetry === false) {
|
|
156
|
+
console.log(`Nixxie telemetry ${auxverb} ${r`disabled`}`)
|
|
157
|
+
console.log()
|
|
158
|
+
printNext(telemetry)
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
console.log(`Nixxie telemetry ${auxverb} ${g`enabled`}`)
|
|
163
|
+
console.log()
|
|
164
|
+
|
|
165
|
+
console.log(` Device telemetry was last sent on ${telemetry.device.lastSentDate}`)
|
|
166
|
+
for (const [projectPath, project] of Object.entries(telemetry.projects)) {
|
|
167
|
+
console.log(
|
|
168
|
+
` Project telemetry for "${y(projectPath)}" was last sent on ${project?.lastSentDate}`
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
console.log()
|
|
173
|
+
printNext(telemetry)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function inform(telemetry: TelemetryOK, userConfig: Configuration) {
|
|
177
|
+
console.log() // gap to help visiblity
|
|
178
|
+
console.log(`${bold('Nixxie Telemetry')}`)
|
|
179
|
+
console.log(`${y`Nixxie collects anonymous data when you run`} ${g`"nixxie dev"`}`)
|
|
180
|
+
console.log(
|
|
181
|
+
`You can use ${g`"nixxie telemetry --help"`} to update your preferences at any time`
|
|
182
|
+
)
|
|
183
|
+
if (telemetry.informedAt === null) {
|
|
184
|
+
console.log()
|
|
185
|
+
console.log(`No telemetry data has been sent as part of this notice`)
|
|
186
|
+
}
|
|
187
|
+
console.log()
|
|
188
|
+
printNext(telemetry)
|
|
189
|
+
console.log() // gap to help visiblity
|
|
190
|
+
console.log(
|
|
191
|
+
`For more information, including how to opt-out see ${grey`https://nixxieinternational.com/telemetry`} (updated ${b`2024-08-20`})`
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
// update the informedAt
|
|
195
|
+
telemetry.informedAt = new Date().toJSON()
|
|
196
|
+
userConfig.set('telemetry', telemetry)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async function sendEvent(eventType: 'project', eventData: Project): Promise<void>
|
|
200
|
+
async function sendEvent(eventType: 'device', eventData: Device): Promise<void>
|
|
201
|
+
async function sendEvent(eventType: 'project' | 'device', eventData: Project | Device) {
|
|
202
|
+
const endpoint = process.env.NIXXIE_TELEMETRY_ENDPOINT || defaultTelemetryEndpoint
|
|
203
|
+
await new Promise<void>(resolve => {
|
|
204
|
+
const req = https.request(
|
|
205
|
+
`${endpoint}${eventType}`,
|
|
206
|
+
{
|
|
207
|
+
method: 'POST',
|
|
208
|
+
headers: {
|
|
209
|
+
'Content-Type': 'application/json',
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
() => resolve()
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
req.once('error', err => {
|
|
216
|
+
log(err?.message ?? err)
|
|
217
|
+
resolve()
|
|
218
|
+
})
|
|
219
|
+
req.end(JSON.stringify(eventData))
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
log(`sent ${eventType} report`)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async function sendProjectTelemetryEvent(
|
|
226
|
+
cwd: string,
|
|
227
|
+
lists: Record<string, InitialisedList>,
|
|
228
|
+
dbProviderName: DatabaseProvider,
|
|
229
|
+
telemetry: TelemetryOK,
|
|
230
|
+
userConfig: Configuration
|
|
231
|
+
) {
|
|
232
|
+
const project = telemetry.projects[cwd] ?? { lastSentDate: null }
|
|
233
|
+
const { lastSentDate } = project
|
|
234
|
+
if (lastSentDate && lastSentDate === todaysDate) {
|
|
235
|
+
log('project telemetry already sent today')
|
|
236
|
+
return
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
await sendEvent('project', {
|
|
240
|
+
lastSentDate,
|
|
241
|
+
packages: await collectPackageVersions(),
|
|
242
|
+
database: dbProviderName,
|
|
243
|
+
lists: Object.keys(lists).length,
|
|
244
|
+
fields: collectFieldCount(lists),
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
// update the project lastSentDate
|
|
248
|
+
telemetry.projects[cwd] = { lastSentDate: todaysDate }
|
|
249
|
+
userConfig.set('telemetry', telemetry)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
async function sendDeviceTelemetryEvent(telemetry: TelemetryOK, userConfig: Configuration) {
|
|
253
|
+
const { lastSentDate } = telemetry.device
|
|
254
|
+
if (lastSentDate && lastSentDate === todaysDate) {
|
|
255
|
+
log('device telemetry already sent today')
|
|
256
|
+
return
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
await sendEvent('device', {
|
|
260
|
+
lastSentDate,
|
|
261
|
+
os: platform(),
|
|
262
|
+
node: process.versions.node.split('.')[0],
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
// update the device lastSentDate
|
|
266
|
+
telemetry.device = { lastSentDate: todaysDate }
|
|
267
|
+
userConfig.set('telemetry', telemetry)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export async function runTelemetry(
|
|
271
|
+
cwd: string,
|
|
272
|
+
lists: Record<string, InitialisedList>,
|
|
273
|
+
dbProviderName: DatabaseProvider
|
|
274
|
+
) {
|
|
275
|
+
try {
|
|
276
|
+
if (ci.isCI) {
|
|
277
|
+
console.log(`Nixxie Telemetry is ${r`disabled`} (running in CI)`)
|
|
278
|
+
return
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const { telemetry, userConfig } = getTelemetryConfig()
|
|
282
|
+
if (telemetry === false) {
|
|
283
|
+
console.log(`Nixxie Telemetry is ${r`disabled`} (via opt-out)`)
|
|
284
|
+
return
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (process.env.NIXXIE_TELEMETRY_DISABLED === '1') {
|
|
288
|
+
console.log(`Nixxie Telemetry is ${r`disabled`} (NIXXIE_TELEMETRY_DISABLED is set)`)
|
|
289
|
+
return
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (process.env.DO_NOT_TRACK === '1') {
|
|
293
|
+
console.log(`Nixxie Telemetry is ${r`disabled`} (DO_NOT_TRACK is set)`)
|
|
294
|
+
return
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (process.env.NODE_ENV === 'production') {
|
|
298
|
+
console.log(`Nixxie Telemetry is ${r`disabled`} (NODE_ENV is production)`)
|
|
299
|
+
return
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// don't send telemetry before we inform the user, allowing opt-out
|
|
303
|
+
const telemetryDefaulted = getDefault(telemetry)
|
|
304
|
+
if (!telemetryDefaulted.informedAt) return inform(telemetryDefaulted, userConfig)
|
|
305
|
+
|
|
306
|
+
console.log(`Nixxie Telemetry is ${g`enabled`}`)
|
|
307
|
+
|
|
308
|
+
await sendProjectTelemetryEvent(cwd, lists, dbProviderName, telemetryDefaulted, userConfig)
|
|
309
|
+
await sendDeviceTelemetryEvent(telemetryDefaulted, userConfig)
|
|
310
|
+
} catch (err: any) {
|
|
311
|
+
log(err?.message ?? err)
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
export function statusTelemetry(updated = false) {
|
|
315
|
+
const { telemetry } = getTelemetryConfig()
|
|
316
|
+
printTelemetryStatus(telemetry, updated)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export function informTelemetry() {
|
|
320
|
+
const { userConfig } = getTelemetryConfig()
|
|
321
|
+
inform(getDefault(false), userConfig)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export function enableTelemetry() {
|
|
325
|
+
const { telemetry, userConfig } = getTelemetryConfig()
|
|
326
|
+
if (!telemetry) {
|
|
327
|
+
userConfig.set('telemetry', getDefault(telemetry))
|
|
328
|
+
}
|
|
329
|
+
statusTelemetry(true)
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export function disableTelemetry() {
|
|
333
|
+
const { userConfig } = getTelemetryConfig()
|
|
334
|
+
userConfig.set('telemetry', false)
|
|
335
|
+
statusTelemetry(true)
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export function resetTelemetry() {
|
|
339
|
+
const { userConfig } = getTelemetryConfig()
|
|
340
|
+
userConfig.delete('telemetry')
|
|
341
|
+
statusTelemetry(true)
|
|
342
|
+
}
|