Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ packages/internal/generated-clients/src/

# put module specific ignore paths here
packages/game-bridge/scripts/**/*.js
packages/audience/sdk/rollup.dts.config.js
packages/audience/sdk/tsup.config.js
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ examples/**/test-results/

tests/**/.env
tests/**/playwright-report/
tests/**/test-results/
tests/**/test-results/

*.prepack-backup
15 changes: 12 additions & 3 deletions packages/audience/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@
"@swc/jest": "^0.2.37",
"@types/jest": "^29.5.12",
"@types/node": "^22.10.7",
"esbuild-plugin-replace": "^1.4.0",
"esbuild-plugins-node-modules-polyfill": "^1.6.7",
"eslint": "^8.56.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.4.3",
"rollup": "^4.22.4",
"rollup-plugin-dts": "^6.4.1",
"ts-jest": "^29.1.0",
"tsup": "^8.3.0",
"typescript": "^5.6.2"
Expand All @@ -36,7 +40,9 @@
"default": "./dist/node/index.js"
}
},
"files": ["dist"],
"files": [
"dist"
],
"homepage": "https://github.com/immutable/ts-immutable-sdk#readme",
"main": "dist/node/index.cjs",
"module": "dist/node/index.js",
Expand All @@ -47,9 +53,12 @@
"repository": "immutable/ts-immutable-sdk.git",
"scripts": {
"build": "pnpm transpile && pnpm typegen",
"transpile": "tsup src/index.ts --config ../../../tsup.config.js",
"typegen": "tsc --customConditions default --emitDeclarationOnly --outDir dist/types",
"transpile": "tsup --config tsup.config.js",
"typegen": "tsc --customConditions default --emitDeclarationOnly --outDir dist/types && rollup -c rollup.dts.config.js && find dist/types -name '*.d.ts' ! -name 'index.d.ts' -delete",
"lint": "eslint ./src --ext .ts,.jsx,.tsx --max-warnings=0",
"pack:root": "pnpm pack --pack-destination $(dirname $(pnpm root -w))",
"prepack": "node scripts/prepack.mjs",
"postpack": "node scripts/postpack.mjs",
"test": "jest --passWithNoTests",
"test:watch": "jest --watch",
"typecheck": "tsc --customConditions development --noEmit --jsx preserve"
Expand Down
17 changes: 17 additions & 0 deletions packages/audience/sdk/rollup.dts.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Roll up the generated .d.ts files so that type re-exports from
// `@imtbl/audience-core` (and its transitive `@imtbl/metrics`) are inlined
// into a single self-contained declaration file. Without this, consumers of
// the published tarball would get unresolved type references, because the
// @imtbl/* packages are bundled into dist/ but not published alongside.
import { dts } from 'rollup-plugin-dts';

// By default, rollup treats every non-relative import as external — so
// `@imtbl/audience-core` type re-exports would stay as bare imports in the
// output. Pass `respectExternal: true` so the plugin walks through node
// resolution to `.d.ts` files for @imtbl/* workspace packages and inlines
// them into the rolled-up declaration file.
export default {
input: 'dist/types/index.d.ts',
output: { file: 'dist/types/index.d.ts', format: 'es' },
plugins: [dts({ respectExternal: true })],
};
17 changes: 17 additions & 0 deletions packages/audience/sdk/scripts/bundled-workspace-deps.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Single source of truth for @imtbl/* workspace packages that get bundled
// into the published @imtbl/audience package.
//
// Used by:
// - ../tsup.config.js (noExternal: inlines the runtime code at build time)
// - ./prepack.mjs (strips workspace:* specifiers from package.json
// before pnpm pack, since these deps are bundled
// into dist/ and @imtbl/audience-core is private)
//
// Adding a new direct @imtbl/* workspace dep to @imtbl/audience? Add it
// here. Otherwise tsup will leave the import as external (broken at runtime
// in consumer projects) or prepack will leave a workspace:* specifier in
// the published package.json (breaks `npm install @imtbl/audience`).
export const BUNDLED_WORKSPACE_DEPS = [
'@imtbl/audience-core',
'@imtbl/metrics',
];
18 changes: 18 additions & 0 deletions packages/audience/sdk/scripts/postpack.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env node
/*
* postpack: restore the package.json that prepack.mjs backed up.
*
* Runs after `npm pack` / `npm publish` finishes, so the developer's working
* tree goes back to referencing `@imtbl/audience-core: workspace:*` for
* local monorepo development.
*/
import { existsSync, copyFileSync, unlinkSync } from 'node:fs';

const pkgPath = new URL('../package.json', import.meta.url);
const backupPath = new URL('../package.json.prepack-backup', import.meta.url);

if (existsSync(backupPath)) {
copyFileSync(backupPath, pkgPath);
unlinkSync(backupPath);
console.log('[postpack] restored original package.json');
}
34 changes: 34 additions & 0 deletions packages/audience/sdk/scripts/prepack.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env node
/*
* prepack: strip workspace-protocol deps from package.json before `npm pack`.
*
* The runtime JS (dist/node, dist/browser) and the bundled .d.ts already
* inline `@imtbl/audience-core` and its transitive `@imtbl/metrics` dep, so
* they don't need to be listed as runtime deps in the published package. If
* we left them, npm would choke on the `workspace:*` protocol at install.
*
* A sibling postpack.mjs restores the original package.json after the tarball
* is written, so the developer's working tree is never left modified.
*/
import { readFileSync, writeFileSync, copyFileSync } from 'node:fs';
import { BUNDLED_WORKSPACE_DEPS } from './bundled-workspace-deps.mjs';

const pkgPath = new URL('../package.json', import.meta.url);
const backupPath = new URL('../package.json.prepack-backup', import.meta.url);

copyFileSync(pkgPath, backupPath);
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));

// Deps bundled into dist/ by tsup: remove from published metadata so
// `npm install @imtbl/audience` doesn't try to resolve them from the
// registry (audience-core is private and never published).
for (const name of BUNDLED_WORKSPACE_DEPS) {
if (pkg.dependencies) delete pkg.dependencies[name];
}
// Clean up empty dependencies object.
if (pkg.dependencies && Object.keys(pkg.dependencies).length === 0) {
delete pkg.dependencies;
}

writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
console.log('[prepack] stripped bundled workspace deps from package.json');
75 changes: 75 additions & 0 deletions packages/audience/sdk/tsup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// @ts-check
// Local tsup config for @imtbl/audience.
//
// Overrides the monorepo's root tsup config by setting `noExternal` to the
// explicit list of `@imtbl/*` workspace deps that should be inlined into the
// built bundle. The same list is used by scripts/prepack.mjs to strip those
// deps from the published package.json. Keeping the two in sync via a shared
// module prevents the "tsup silently bundles a new dep but prepack leaves
// workspace:* in package.json" class of bugs.
import { defineConfig } from 'tsup';
import { nodeModulesPolyfillPlugin } from 'esbuild-plugins-node-modules-polyfill';
import { replace } from 'esbuild-plugin-replace';
import pkg from './package.json' with { type: 'json' };
import { BUNDLED_WORKSPACE_DEPS } from './scripts/bundled-workspace-deps.mjs';

export default defineConfig((options) => {
if (options.watch) {
return {
entry: ['src/index.ts'],
outDir: 'dist/browser',
format: 'esm',
target: 'es2022',
platform: 'browser',
bundle: true,
noExternal: BUNDLED_WORKSPACE_DEPS,
esbuildPlugins: [
nodeModulesPolyfillPlugin({
globals: { Buffer: true, process: true },
modules: ['crypto', 'buffer', 'process'],
}),
replace({
__SDK_VERSION__: pkg.version === '0.0.0' ? '2.0.0' : pkg.version,
}),
],
};
}

return [
// Browser ESM bundle
{
entry: ['src/index.ts'],
outDir: 'dist/browser',
platform: 'browser',
format: 'esm',
target: 'es2022',
minify: true,
bundle: true,
noExternal: BUNDLED_WORKSPACE_DEPS,
treeshake: true,
esbuildPlugins: [
nodeModulesPolyfillPlugin({
globals: { Buffer: true, process: true },
modules: ['crypto', 'buffer', 'process'],
}),
replace({ __SDK_VERSION__: pkg.version }),
],
},

// Node CJS + ESM bundle
{
entry: ['src/index.ts'],
outDir: 'dist/node',
platform: 'node',
format: ['esm', 'cjs'],
target: 'es2022',
minify: true,
bundle: true,
noExternal: BUNDLED_WORKSPACE_DEPS,
treeshake: true,
esbuildPlugins: [
replace({ __SDK_VERSION__: pkg.version }),
],
},
];
});
Loading
Loading