Node: JSON configs are read as data, not imported (store-only apps failed under npx: needs an import attribute); test, pitfall 105

This commit is contained in:
CRTkafa 2026-10-22 23:18:30 +08:00
parent bd316723f5
commit d3d31d6c12
4 changed files with 24 additions and 0 deletions

View file

@ -2,6 +2,8 @@
## Unreleased
- Node: a `storebound.config.json` (and every store-only app) loads again; it needed an import attribute. Pitfall 105.
- **`storebound watch`**: store events for every app on the machine (rejected, approved, live, rollout halted, crash
threshold, low or unanswered reviews), sent to ntfy (phone), Telegram, a webhook or an OS notification; runs as a loop
(`--every 15m`) or `--once`; a PM2 recipe for a server is in docs/watch.md. `storebound events` and the MCP tool

View file

@ -82,6 +82,9 @@ export const importPath = (path: string): Promise<any> => import(pathToFileURL(p
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export async function importConfigModule(path: string): Promise<any> {
// a JSON config is read, not imported: Node refuses a JSON import without `with { type: 'json' }` (every store-only
// app of `storebound watch` on a server failed; pitfall 105)
if (/\.json$/i.test(path)) return { default: JSON.parse(readFileSync(path, 'utf8')) };
if (isBun || !/\.[cm]?ts$/.test(path)) return importPath(path);
try {
return await withoutTypeStripWarning(() => importPath(path));

View file

@ -1265,3 +1265,10 @@ that fails without the fix (see CONTRIBUTING.md).
- **Guard:** `iapLocalizationChanges` / `iapAttributeChanges` / `availabilityChange` (`cli/apple/iap.ts`), the
subscription helpers in `cli/lib/subscriptions.ts`, `planAppInfo` / `reviewDetailDiff`, `campaignDiff`,
`winBackDiff`, `eventAttrDiff`; tests `apple-iap-drift`, `subscriptions-drift`, `appinfo-drift`, `misc-drift`.
## 105. `storebound watch` on a server read no app: "needs an import attribute of type: json"
- **Symptom:** on Node (npx, a server), every store-only app failed with `Module ".../storebound.config.json" needs an
import attribute of "type: json"`; on Bun it worked.
- **Cause:** a JSON config (store-only apps get one generated) was loaded with a bare dynamic import, which Node refuses.
- **Do:** update storebound.
- **Guard:** `importConfigModule` in `cli/lib/rt.ts` reads JSON configs as data (`tests/config-json-node.test.ts`).

View file

@ -0,0 +1,12 @@
// A storebound.config.json loads without an import attribute (Node refuses a bare JSON import; pitfall 105).
import { expect, test } from 'bun:test';
import { mkdtempSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { importConfigModule } from '../cli/lib/rt';
test('importConfigModule reads a JSON config as data', async () => {
const f = join(mkdtempSync(join(tmpdir(), 'sb-json-')), 'storebound.config.json');
writeFileSync(f, JSON.stringify({ app: { name: 'Demo' }, play: { packageName: 'com.example.demo' } }));
expect((await importConfigModule(f)).default.play.packageName).toBe('com.example.demo');
});