Files
zeekay ec6f6b50c1 chore: kill ALL posthog — zero refs, zero filenames (1452 -> 0)
We own the ingestion server (hanzoai/insights: Django + rust/capture + nodejs
plugin) AND this SDK, so there is no external wire contract to preserve. The
server is already 100% posthog-free; this SDK was the last laggard.

- $last_posthog_reset -> $last_insights_reset. This FIXES A LIVE MISMATCH: the
  server taxonomy (insights/taxonomy/taxonomy.py, insights/insightsql/ai.py)
  already expected the insights form while the SDK emitted the posthog form.
- __PosthogExtensions__ -> __InsightsExtensions__; all PostHog/posthog/POSTHOG
  identifiers -> Insights/insights/INSIGHTS (src, tests, playground, playwright,
  scripts, rrweb subpackages, package.json keywords).
- Hosts: DEFAULT_PLUGIN_HOST + DEFAULT_NUXT_HOST + the core host default pointed
  at PostHog's cloud (us.i.posthog.com) — a real bug. All -> insights.hanzo.ai.
- Removed the us-assets/eu-assets CDN split in getRemoteConfig (PostHog-specific;
  Hanzo serves remote config from the same host) — it had degenerated to a no-op.
- Fixed generate-docs writing to a stray references/@hanzo/ subdir.
- Renamed the 3 posthog-named test files; dropped 58MB of stale reference
  snapshots named for upstream posthog versions we never shipped (they are
  generated output — references/ is now gitignored).

Verified: typecheck errors 42 (HEAD) -> 18 (all pre-existing test-mock
looseness); types package 0; every package.json valid with @hanzo/* names.
Guard: grep -rioE 'posthog' packages ... | wc -l  => 0
2026-07-16 09:09:18 -07:00

126 lines
5.4 KiB
TypeScript

import {
addInsightsWithBundledScriptsToBundleShellScript,
disableUserScriptSandboxing,
modifyExistingXcodeBuildScript,
} from '../src/tooling/expoconfig'
type MockBuildConfig = { buildSettings: Record<string, string> }
const mockXcodeProject = (): {
pbxXCBuildConfigurationSection: () => Record<string, MockBuildConfig>
configs: Record<string, MockBuildConfig>
} => {
const configs: Record<string, MockBuildConfig> = {
'1A:Release': { buildSettings: { PRODUCT_NAME: '"MyApp"' } },
'2B:Debug': { buildSettings: { PRODUCT_NAME: '"MyApp"' } },
'3C:Pods-Release': { buildSettings: { PRODUCT_NAME: '"Pods-MyApp"' } },
}
return {
pbxXCBuildConfigurationSection: () => configs,
configs,
}
}
describe('disableUserScriptSandboxing', () => {
it('sets ENABLE_USER_SCRIPT_SANDBOXING="NO" on every build configuration', () => {
const xp = mockXcodeProject()
disableUserScriptSandboxing(xp)
for (const key of Object.keys(xp.configs)) {
expect(xp.configs[key].buildSettings.ENABLE_USER_SCRIPT_SANDBOXING).toBe('"NO"')
}
})
it('uses the literal quoted "NO" string required by the pbxproj format', () => {
// Unquoted NO corrupts the project file in some xcode-npm versions.
const xp = mockXcodeProject()
disableUserScriptSandboxing(xp)
expect(xp.configs['1A:Release'].buildSettings.ENABLE_USER_SCRIPT_SANDBOXING).not.toBe('NO')
expect(xp.configs['1A:Release'].buildSettings.ENABLE_USER_SCRIPT_SANDBOXING).not.toBe(false)
})
it('preserves existing build settings', () => {
const xp = mockXcodeProject()
disableUserScriptSandboxing(xp)
expect(xp.configs['1A:Release'].buildSettings.PRODUCT_NAME).toBe('"MyApp"')
})
it('is idempotent — running twice yields the same result', () => {
const xp = mockXcodeProject()
disableUserScriptSandboxing(xp)
disableUserScriptSandboxing(xp)
expect(xp.configs['1A:Release'].buildSettings.ENABLE_USER_SCRIPT_SANDBOXING).toBe('"NO"')
})
})
// Extracts the argument that would become $1 inside insights-xcode.sh when
// the wrapped line is executed by the shell. The shell runs:
// /bin/sh <insights-xcode.sh-path> <...rest>
// so $1 is the token immediately after the insights-xcode.sh path.
const extractArg1 = (wrappedLine: string): string => {
// The line looks like: /bin/sh `<node eval>` <arg1> ...
// Split on the backtick-delimited insights-xcode.sh path expression, then
// take the first whitespace-separated token from whatever follows it.
const afterInsights = wrappedLine.split(/`[^`]+`/)[1] ?? ''
return afterInsights.trim().split(/\s+/)[0]
}
describe('addInsightsWithBundledScriptsToBundleShellScript', () => {
it('wraps the react-native-xcode.sh invocation with insights-xcode.sh', () => {
const original = '"../node_modules/react-native/scripts/react-native-xcode.sh"'
const wrapped = addInsightsWithBundledScriptsToBundleShellScript(original)
expect(wrapped).toContain('insights-xcode.sh')
expect(wrapped).toContain('react-native-xcode.sh')
expect(wrapped.startsWith('/bin/sh ')).toBe(true)
expect(wrapped.indexOf('insights-xcode.sh')).toBeLessThan(wrapped.indexOf('react-native-xcode.sh'))
})
it('supports the alternative packager/ path', () => {
const original = '"node_modules/react-native/packager/react-native-xcode.sh"'
const wrapped = addInsightsWithBundledScriptsToBundleShellScript(original)
expect(wrapped).toContain('insights-xcode.sh')
expect(wrapped).toContain('packager/react-native-xcode.sh')
})
// Regression tests for issue #3682:
// When the Expo bundle phase already contains a /bin/sh prefix (common in
// Expo SDK 53+ and plain RN projects), insights-xcode.sh receives /bin/sh as
// $1, which makes the REACT_NATIVE_XCODE variable resolve to /bin/sh instead
// of react-native-xcode.sh, silently breaking the PACKAGER_SOURCEMAP_FILE patch.
it.each([
['simple path (no shell prefix)', '../node_modules/react-native/scripts/react-native-xcode.sh'],
[
'shell-prefixed command (Expo SDK 53+ / plain RN)',
'/bin/sh "$PODS_ROOT/../.."/node_modules/react-native/scripts/react-native-xcode.sh',
],
])('arg1 passed to insights-xcode.sh is react-native-xcode.sh path, not /bin/sh — %s', (_desc, original) => {
const wrapped = addInsightsWithBundledScriptsToBundleShellScript(original)
const arg1 = extractArg1(wrapped)
expect(arg1).toContain('react-native-xcode.sh')
expect(arg1).not.toBe('/bin/sh')
})
})
describe('modifyExistingXcodeBuildScript', () => {
it('wraps the bundle phase shellScript', () => {
const script = { shellScript: JSON.stringify('"../node_modules/react-native/scripts/react-native-xcode.sh"') }
modifyExistingXcodeBuildScript(script)
const parsed = JSON.parse(script.shellScript)
expect(parsed).toContain('insights-xcode.sh')
})
it('is idempotent — re-running does not double-wrap', () => {
const script = { shellScript: JSON.stringify('"../node_modules/react-native/scripts/react-native-xcode.sh"') }
modifyExistingXcodeBuildScript(script)
const firstPass = script.shellScript
modifyExistingXcodeBuildScript(script)
expect(script.shellScript).toBe(firstPass)
})
it('skips scripts that do not invoke react-native-xcode.sh', () => {
const script = { shellScript: JSON.stringify('echo "hello"') }
const original = script.shellScript
modifyExistingXcodeBuildScript(script)
expect(script.shellScript).toBe(original)
})
})