@expokit/cli 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -50,12 +50,16 @@ Everything else — live previews, props, installation, theming, Pro, AI / MCP s
50
50
 
51
51
  ## Security
52
52
 
53
- - **No dependencies, no install scripts, no telemetry.**
53
+ - **No dependencies, no install scripts.**
54
+ - **Anonymous install counts only** — after a successful `add`, the CLI sends the item's name (`{"items":["button"]}`)
55
+ to expokit.in so the site can show how often each component is installed. No token, files, paths or machine details;
56
+ repeat adds count once a day. Turn it off with `DO_NOT_TRACK=1` or `EXPO_KIT_TELEMETRY=0`; it never runs in CI,
57
+ `--dry-run` or `update`.
54
58
  - **Writes only inside your app** — `components.json`, the `@/*` alias in `tsconfig.json` and the component files.
55
59
  `--dry-run` shows every change first; `add` never overwrites a file you changed unless you pass `--force`.
56
60
  `paths` in `components.json` that point outside the app are refused. Symlinks inside the app are followed, not
57
61
  checked, so a cloned repo that symlinks a folder elsewhere can still send writes there.
58
- - **Free components need no network** — they ship inside this package. Pro components are downloaded over HTTPS from
62
+ - **Free components need no network to install** — they ship inside this package. Pro components are downloaded over HTTPS from
59
63
  expokit.in; your token is stored readable only by you, sent only to that site and never through a redirect.
60
64
  In scripts, pipe it to `login` or set `EXPO_KIT_TOKEN` (`--token` leaves it in your shell history).
61
65
  - **Runs one command:** `npx expo install` for the packages a component needs — without `EXPO_KIT_TOKEN` in its
package/bin/expo-kit.js CHANGED
@@ -34,6 +34,7 @@ import {
34
34
  retryDelayMs,
35
35
  retryHint,
36
36
  tabComponentName,
37
+ telemetryEnabled,
37
38
  needsDevBuild,
38
39
  pickMainExport,
39
40
  } from './lib.mjs';
@@ -942,12 +943,33 @@ function cmdInit(cwd, flags, dir) {
942
943
  log(`Done. Add items with: ${RUN} add <name>`);
943
944
  }
944
945
 
945
- async function cmdAdd(args, cwd) {
946
+ /**
947
+ * After a successful add: tells the site which item was installed — just its name, no token or project
948
+ * data (README "Privacy"). Off with DO_NOT_TRACK=1 / EXPO_KIT_TELEMETRY=0 and in CI. Never fails the add.
949
+ */
950
+ async function reportInstalled(name) {
951
+ if (!telemetryEnabled(process.env)) return;
952
+ try {
953
+ parseSiteUrl(SITE_URL);
954
+ const res = await fetch(`${SITE_URL}/api/cli/installed`, {
955
+ method: 'POST',
956
+ headers: { 'content-type': 'application/json' },
957
+ body: JSON.stringify({ items: [name] }),
958
+ signal: AbortSignal.timeout(1500),
959
+ });
960
+ await res.arrayBuffer();
961
+ } catch {
962
+ // offline, slow or blocked: the count just misses this one
963
+ }
964
+ }
965
+
966
+ /** `report: false` for re-adds that aren't new installs (`update --force`). */
967
+ async function cmdAdd(args, cwd, { report = true } = {}) {
946
968
  const { flags, positional } = parseFlags(args);
947
969
  // `add a b c` → add each in turn with the same flags.
948
970
  if (positional.length > 1 && !positional.includes('--list')) {
949
971
  const flagArgs = args.filter((a) => a.startsWith('--'));
950
- for (const item of positional) await cmdAdd([item, ...flagArgs], cwd);
972
+ for (const item of positional) await cmdAdd([item, ...flagArgs], cwd, { report });
951
973
  return;
952
974
  }
953
975
  const name = positional[0];
@@ -1049,6 +1071,7 @@ async function cmdAdd(args, cwd) {
1049
1071
  const depsOk = runExpoInstall(projectRoot, meta.dependencies ?? [], false);
1050
1072
 
1051
1073
  if (depsOk) markTemplateInstalled(projectRoot, config, resolved);
1074
+ if (report) await reportInstalled(resolved);
1052
1075
 
1053
1076
  console.log('');
1054
1077
  if (resolved === 'liquidglass-tab') {
@@ -1092,7 +1115,7 @@ async function cmdUpdate(args, cwd) {
1092
1115
  if (flags.force) {
1093
1116
  for (const resolved of targets) {
1094
1117
  log(`Full overwrite ${resolved} (--force${flags.dryRun ? ', dry run' : ''})…\n`);
1095
- await cmdAdd([resolved, '--force', ...(flags.dryRun ? ['--dry-run'] : [])], cwd);
1118
+ await cmdAdd([resolved, '--force', ...(flags.dryRun ? ['--dry-run'] : [])], cwd, { report: false });
1096
1119
  }
1097
1120
  return;
1098
1121
  }
package/bin/lib.mjs CHANGED
@@ -318,6 +318,7 @@ export function kitVersion(text) {
318
318
  */
319
319
  export const EXPO_GO_PACKAGES = new Set([
320
320
  '@expo/vector-icons',
321
+ '@react-native-async-storage/async-storage',
321
322
  '@shopify/react-native-skia',
322
323
  'expo-blur',
323
324
  'expo-charts',
@@ -325,6 +326,7 @@ export const EXPO_GO_PACKAGES = new Set([
325
326
  'expo-haptics',
326
327
  'expo-router',
327
328
  'expo-splash-screen',
329
+ 'expo-status-bar',
328
330
  'react-native-gesture-handler',
329
331
  'react-native-reanimated',
330
332
  'react-native-safe-area-context',
@@ -366,6 +368,18 @@ export function mergeDependencies(...lists) {
366
368
 
367
369
  export const DEFAULT_SITE_URL = 'https://expokit.in';
368
370
 
371
+ const OFF = /^(0|false|off|no)$/i;
372
+ const set = (v) => v !== undefined && v !== '' && !OFF.test(v);
373
+
374
+ /**
375
+ * Anonymous install counts (README "Privacy"): on unless DO_NOT_TRACK is set, EXPO_KIT_TELEMETRY is
376
+ * 0/false/off/no, or it's a CI run (builds re-adding items aren't new installs).
377
+ */
378
+ export function telemetryEnabled(env) {
379
+ if (set(env.DO_NOT_TRACK) || set(env.CI)) return false;
380
+ return !(env.EXPO_KIT_TELEMETRY !== undefined && OFF.test(env.EXPO_KIT_TELEMETRY));
381
+ }
382
+
369
383
  export function isLoopbackHost(hostname) {
370
384
  return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]' || hostname === '::1';
371
385
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expokit/cli",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "mcpName": "io.github.Anshkaran7/expokit",
5
5
  "description": "Animated UI components for Expo and React Native — a shadcn-style CLI that copies buttons, inputs, cards, charts and full screens into your app",
6
6
  "license": "MIT",