chore(setup): add SDK init/injection library and templates - #751
Merged
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
DetectResult carries EntryPointExists so callers can tell an entry file the detector found from one it merely suggests, and never write initialization code into a path the project does not load. PackageManager names the tool that manages the project's dependencies: bundle rather than gem when a Gemfile is present, and poetry, uv or pipenv rather than always pip. Locate MainActivity and Main under their real package directory rather than assuming an unqualified class name, derive the Android source root from whichever manifest matched, find the Swift entry point where SwiftPM and Xcode nest it, look for src/main.tsx where Vite mounts a React app, and recognise bun.lockb. Rename the Android SDK ID to android for consistency with the other IDs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ffantl-ld
force-pushed
the
ffantl/setup-ld/3-initializer
branch
from
July 31, 2026 17:47
c56c506 to
6a44381
Compare
Next.js detection targeted whichever page module happened to exist, and node-server is append-safe, so setup wrote server SDK init — including the SDK key — into app/page.tsx or pages/index.tsx. A page module may carry 'use client' or be imported by something that does, which bundles it for the browser, and nothing in the detector can tell which. Only instrumentation.ts, Next's server-startup hook, is guaranteed to stay server-side, so suggest creating it rather than picking a page. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Each candidate list encodes a claim about where a toolchain puts its entry file. Link the documentation that claim rests on so it can be rechecked when the frameworks move. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ffantl-ld
force-pushed
the
ffantl/setup-ld/3-initializer
branch
from
July 31, 2026 18:25
6a44381 to
2efb79d
Compare
A root package.json is often only build tooling — Rails with jsbundling, Django with Tailwind, a Go binary published to npm — so preferring Node whenever one parsed meant those projects were handed the Node SDK. This repo hit it too. Confine the Sources/ search to single-target Swift packages. Across several targets there is no way to tell an executable's entry file from a library's, so an arbitrary hit was reported as found. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The existing tests check one or two fields each, so a field detection stops populating passes as long as the SDK id stays right. Compare the full DetectResult across the project layouts real toolchains produce. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ffantl-ld
force-pushed
the
ffantl/setup-ld/3-initializer
branch
from
August 3, 2026 18:52
2efb79d to
43d2d15
Compare
NestJS and similar apps start from src/main.ts, which the candidate list skipped, so detection suggested a nonexistent index.js. node-server appends to the entry file, so setup created that index.js and left the real entry point without the SDK. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`gem install` left the Gemfile untouched, so the SDK stayed unavailable under bundler and IsInstalled kept returning false. Use `bundle add` when the project is Bundler-managed, and poetry, uv or pipenv when one of those manages the Python dependencies. Unrecognised package managers fall back to pip rather than being run as a command, since the value reaches InstallArgs from the detector. InstallArgs added launchdarkly-react-native-client-sdk, which npm marks deprecated in favour of @launchdarkly/react-native-client-sdk. The unscoped launchdarkly-js-client-sdk is the v3 package whose initialize API the init template uses; the scoped one is v4 and exposes createClient. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
IsInstalled tested for its package name as a substring, so @launchdarkly/node-server-sdk-redis, launchdarkly-server-sdk-otel, and LaunchDarkly.ServerSdk.Telemetry each counted as the SDK itself and the real install was skipped. Require a non-name character on both sides, which every manifest format supplies. Detection accepts a solution with no project file beside it, but install ran a bare `dotnet add package`, which needs the working directory to hold exactly one project. Resolve the project the solution refers to and pass --project; with none or several, stop and say so rather than adding the SDK to an arbitrary assembly. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
react-native.tmpl bound the default export of @launchdarkly/react-native-client-sdk, which has no default export, so the snippet could not compile. The client is the named export ReactNativeLDClient. Register the android template under the SDK ID the detector reports, keeping android-client-sdk as an alias. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Swift and Android snippets did not compile. LDConfig's only public initializer takes autoEnvAttributes, and LDConfig.Builder's only constructor takes AutoEnvAttributes, so neither config could be built as written. These SDKs return a snippet for the user to paste rather than writing a file, so the snippet is the entire deliverable. AutoEnvAttributes is nested in LDConfig.Builder, which the package wildcard import does not cover, so import it explicitly. Add DefaultEntryPoint, naming the file to create for the SDKs that write one when detection found no entry point for them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
LDContextBuilder.build returns a Result, and the snippet unwrapped it with `try ...get()`. try only compiles inside a throwing function, and the places this snippet gets pasted — application(_:didFinishLaunchingWithOptions:) and similar startup hooks — do not throw. Match on the Result instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ffantl-ld
force-pushed
the
ffantl/setup-ld/3-initializer
branch
from
August 3, 2026 19:48
43d2d15 to
8daf723
Compare
Keep TestInstallArgs_PackageMatchesTemplateImport in installer_test.go: it asserts the init templates import the package the installer installs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
InjectIntoFile prepended the import section at byte 0, which displaced a leading shebang and an encoding cookie. Django's manage.py is one of the Python entry points detection targets, so `./manage.py` stopped being executable after setup wrote to it, and Python stopped honoring a coding declaration pushed past line 2. Peel the prologue off first and insert imports after it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The node-server template loaded the SDK with require, but detection targets TypeScript and ESM entry points such as Next.js instrumentation.ts and NestJS src/main.ts, where require is not defined at runtime. Setup wrote that code and reported success, so the failure only showed up when the app started. Pick the CommonJS or ESM template from the entry extension, falling back to the nearest package.json "type" for a plain .js file. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Injecting imports after only the shebang and encoding cookie broke the other constructs a file has to open with. A Python __future__ import below the injected imports is a SyntaxError, a module docstring pushed down is demoted to a plain expression, and Ruby magic comments and a CommonJS 'use strict' are silently ignored once code precedes them. All of it was written with Success: true. Peel the shebang, the leading comment block, and the language's own leading constructs, then insert imports after them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 26827c0. Configure here.
A /* */ license or JSDoc header stopped the prologue scan, so imports landed above it and above the 'use strict' that followed, silently dropping the file out of strict mode. A directive with a trailing same-line comment was missed for the same reason. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
erangeles
approved these changes
Aug 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Describe the solution you've provided
Third layer of the guided
setupcommand: SDK initialization. Renders per-SDK code snippets from embedded templates and injects them into the project (Initializer,RenderTemplate,InjectIntoFile), plus docs-URL helpers. Ships thesdk_init_templates/for the supported SDKs.Independent library layer.
Related issues
Part of the
setup-ldfeature. Stacked PR — base isffantl/setup-ld/2-installer.Requirements
Note
Medium Risk
The library writes user project files on disk for append-safe SDKs; incorrect prologue or module-syntax handling could break entry points, though coverage is extensive.
Overview
Adds the SDK initialization layer for guided
setup: embedded per-SDK templates, rendering withInitConfig, andInjectIntoFilethat either writes runnable init into entry files or returns snippets plus docs links.Append-safe Node, Python, and Ruby server SDKs get imports merged after preserved prologues (shebangs, encoding cookies,
__future__,'use strict') and init appended at file scope. Node picks CommonJSrequirevs ESMimportfrom file extension and nearestpackage.json"type".Go, Java, C#, Swift, Android, React, and React Native do not modify the project;
InitResultcarriesSuccess=false, a copy-pasteSnippet, andDocsURL. Unknown SDKs get docs URLs only. Helpers includeGetDocsURL,InjectsInPlace,DefaultEntryPoint, andSupportedSDKIDs. Tests cover prologue handling, module syntax, guidance-only paths, mobile template correctness, and installer package name alignment with template imports.Reviewed by Cursor Bugbot for commit 1d4cf46. Bugbot is set up for automated code reviews on this repo. Configure here.