-
Notifications
You must be signed in to change notification settings - Fork 0
Managing Modules
This Wiki calls each local generated package a module. The CLI calls the same independently managed package a feature: it is the part you add, update, validate, and remove.
A module has a native C/C++ environment, a Kotlin/Java JVM environment, or both. The plugin-wide runtime is shared, but each module remains independently manageable.
Your implementation normally lives below:
local_modules/<package>/android/src/main/cpp/
local_modules/<package>/android/src/main/java/
These are user-owned source roots. Update preserves files you add there and starter files you intentionally change or delete.
The generator owns the surrounding connection code, including:
-
.supernote-module.json; - package entry points;
-
index.d.ts; - generated JSI and JNI adapters;
- KSP manifests and adapter output;
- generated CMake and Gradle integration;
- feature/package README files; and
-
android/.supernote-module/v2-runtime/.
Do not put durable implementation logic in a generated adapter, declaration, manifest, build file, or runtime source. Put it in the C/C++ or Kotlin/Java source root and use a Supernote marker when the generator needs to know about it.
The generated README inside a feature records the ownership boundary for the generator version that created it.
Update and Remove are transactional, but normal source-control habits still matter.
Before a large change:
git status --short
git diffThen commit, stash, save a patch, or otherwise make sure you can identify your existing work.
You do not need to erase unrelated changes before using the generator. Do not run a broad Git clean or reset merely to make the plugin look tidy.
After upgrading the generator or changing feature integration:
supernote-module update documentThe interactive command shows what it will replace, preserve, and change in the parent plugin. Review that summary before accepting it.
For automation:
supernote-module update document --yes --plainAfter Update:
git status --short
git diff
supernote-module validate document --build --verboseInspect index.d.ts whenever the public API changed.
The feature package version and the complete plugin version are separate.
The feature's --package-version value belongs to the generated local package.
It does not control how PluginHost identifies an update to the complete
.snplg plugin.
Before packaging an installable plugin update, increase versionCode and
versionName in the plugin root's PluginConfig.json, for example:
{
"versionCode": "2",
"versionName": "0.0.2"
}versionCode is the installation/update version. versionName is the version
shown to people. Reinstalling changed code with the same plugin ID and the same
root plugin version may leave the previously installed bundle active. Running
supernote-module update does not increase these root plugin values for you.
Update preserves the C/C++ and Kotlin/Java implementation roots, including:
- functions and classes you wrote;
- ordinary unmarked helpers;
- marked public or internal declarations;
- extra
.c,.cpp,.h,.hpp,.kt, and.javafiles; - starter files you modified; and
- starter files you intentionally removed.
It regenerates the files that connect that implementation to the shared plugin runtime.
Update is not a source converter or feature-renaming command.
It does not:
- translate C++ into Kotlin or Kotlin into C++;
- infer a permanent backend;
- expose unmarked public language members;
- rename the npm package, JavaScript feature name, or Android namespace;
- add V1 compatibility behavior; or
- preserve manual edits made inside generator-owned output.
When an identity really needs to change, create a new feature with the intended name, move the user-owned implementation deliberately, verify it, and then remove the old feature.
Starter selection controls only the first example files.
A module created with:
supernote-module add document --starter cpp --yescan later gain Kotlin or Java under its JVM source root. A module started in the
JVM environment can later gain .c and .cpp files under its native source
root.
There is no conversion step and no metadata switch. Add the source, mark only the declarations that need generated routing, then run:
supernote-module update document --yes
supernote-module validate document --build --verboseSee Using Both Environments when native C++ needs to call Kotlin or Java through generated internal routing.
Add writes a local file: dependency into the parent package.json. Update and
Remove refresh npm or Yarn only when the package metadata or local link needs
it.
--skip-install skips the package-manager command. It does not undo the
package.json change.
If you skip installation, refresh dependencies yourself before expecting
node_modules/<feature> to exist:
npm installor:
yarn installIf both lockfiles exist, the CLI asks you to resolve the ambiguity or pass
--package-manager explicitly.
For a quick structure and integration check:
supernote-module validate documentAfter changing marked declarations, use the build path:
supernote-module validate document --build --verboseThe build is where KSP sees Kotlin/Java source and the common generator rebuilds the final TypeScript and native routes.
A passing local build proves generation and compilation in that environment. It does not prove that the target PluginHost can load the library or survive a same-process plugin reload.
supernote-module validate --allFor machine-readable CI output:
supernote-module validate --all --json--all reports all feature failures before returning failure instead of
stopping after the first one.
Interactive removal asks you to type the exact package name:
supernote-module remove documentFor automation, make the target explicit:
supernote-module remove document --yes --plainRemove updates the parent dependency and rebuilds the shared runtime registry without the selected feature.
The transaction keeps implementation source recoverable until the parent changes, dependency refresh, and final checks have succeeded.
Interactive removal of everything requires typing:
REMOVE ALL
Start it with:
supernote-module remove --allFor automation:
supernote-module remove --all --yes --plain--yes is accepted only when the target is already unambiguous. It never turns
a missing target into “all features.”
Remove leaves build output alone, even when --yes is present.
To remove the three documented plugin build directories as part of the same operation, opt in explicitly:
supernote-module remove document --delete-build-files --yesThe cleanup scope is exactly:
build/
android/build/
android/app/build/
It does not delete global Gradle caches, arbitrary CMake directories, Android SDK files, or user-owned source outside the selected feature.
Before a mutating operation changes the plugin, it stages data and records a transaction journal. If the process is interrupted, the next command attempts recovery before starting new work.
Exit code 3 means recovery still needs attention.
Do not delete the journal or staging directory blindly. They may contain the only remaining copy of source that was temporarily detached during the transaction.
Start with:
supernote-module doctor --verbose
git status --short
git diffThen follow the exact recovery instructions printed by the CLI. Preserve the plugin and transaction files before attempting a manual repair.
If a feature needs custom Gradle, CMake, JNI, JSI, or KSP behavior that the generator does not expose, do not quietly patch a generated file and assume Update will preserve it.
First ask whether the customization can live in user-owned source or an ordinary library dependency. If it truly requires a generator change, treat it as a generator capability and test it there.
V2 does not include a V1 converter, migration analyzer, compatibility mode, or source-rewriting tool. V1 was an implementation baseline, not a supported input format.
If an experimental V1 project needs V2, create V2 features and move the implementation source deliberately.