Skip to content

Commit 3a5a594

Browse files
authored
chore: adding shopify oxygen example (#997)
This PR will add an example application for Shopify Oxygen SDK <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds a runnable Shopify Oxygen SDK example (with mini-oxygen runner) and includes it in the root workspaces. > > - **Examples**: > - **Shopify Oxygen SDK example** in `packages/sdk/shopify-oxygen/example`: > - `src/index.ts`: Minimal worker that initializes `@launchdarkly/shopify-oxygen-sdk`, evaluates a flag, and returns JSON. > - `app.ts`: Local runner using `@shopify/mini-oxygen` to repeatedly invoke the worker and print results. > - `README.md`: Setup and run instructions. > - Build setup: `package.json` (scripts/deps), `tsconfig.json`, `tsup.config.ts`. > - **Repo**: > - Update root `package.json` workspaces to include `packages/sdk/shopify-oxygen/example`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 8cc1f7e. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent d1d11f1 commit 3a5a594

File tree

7 files changed

+208
-1
lines changed

7 files changed

+208
-1
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
"contract-tests",
4444
"packages/sdk/combined-browser",
4545
"packages/sdk/shopify-oxygen",
46-
"packages/sdk/shopify-oxygen/contract-tests"
46+
"packages/sdk/shopify-oxygen/contract-tests",
47+
"packages/sdk/shopify-oxygen/example"
4748
],
4849
"private": true,
4950
"scripts": {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# LaunchDarkly sample Shopify Oxygen application
2+
3+
We've built a simple console application that demonstrates how this LaunchDarkly SDK works.
4+
5+
Below, you'll find the build procedure. For more comprehensive instructions, you can visit your [Quickstart page](https://app.launchdarkly.com/quickstart#/).
6+
<!-- NOTE: no official docs in LD website yet
7+
or the [{name of SDK} reference guide](https://docs.launchdarkly.com/sdk/{path to the page for that SDK}).
8+
-->
9+
10+
This demo requires `Node >= 22.0.0` and `yarn@^3.4.1`
11+
12+
## Build instructions
13+
14+
1. Edit [`src/index.ts`](src/index.ts) and set the value of `sdkKey` to your LaunchDarkly SDK key.
15+
```
16+
const sdkKey = "1234567890abcdef";
17+
```
18+
19+
2. If there is an existing boolean feature flag in your LaunchDarkly project that
20+
you want to evaluate, set `flagKey` to the flag key:
21+
```
22+
const flagKey = "my-flag-key";
23+
```
24+
> Otherwise, `sample-feature` will be used by default.
25+
26+
3. On the command line, run `yarn start`, You should receive the message:
27+
```
28+
The {flagKey} feature flag evaluates to {flagValue}.
29+
```
30+
The application will run continuously and react to the flag changes in LaunchDarkly.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { createMiniOxygen } from '@shopify/mini-oxygen';
2+
3+
/* eslint-disable no-console */
4+
5+
/**
6+
* This is script is a simple runner for our example app. This script will run
7+
* the compiled example on a local worker implementation to emulate a Oxygen worker runtime.
8+
*
9+
* For the actual example implementation, see the src/index.ts file.
10+
*/
11+
12+
const printValueAndBanner = (flagKey: string, flagValue: string) => {
13+
console.log(`*** The '${flagKey}' feature flag evaluates to ${flagValue}.`);
14+
15+
if (flagValue) {
16+
console.log(
17+
` ██
18+
██
19+
████████
20+
███████
21+
██ LAUNCHDARKLY █
22+
███████
23+
████████
24+
██
25+
██
26+
`,
27+
);
28+
}
29+
};
30+
31+
const main = async () => {
32+
// NOTE: you will see logging coming from mini-oxygen's default request hook.
33+
// https://github.com/Shopify/hydrogen/blob/5a38948133766e358c5f357f52562f6fdcfe7969/packages/mini-oxygen/src/worker/index.ts#L225
34+
const miniOxygen = createMiniOxygen({
35+
debug: false,
36+
workers: [
37+
{
38+
name: 'main',
39+
modules: true,
40+
scriptPath: 'dist/index.js',
41+
},
42+
],
43+
});
44+
45+
miniOxygen.ready.then(() => {
46+
console.log('Oxygen worker is started...');
47+
console.log('Press "q" or Ctrl+C to quit...');
48+
49+
// Dispatch fetch every 5 seconds
50+
const interval = setInterval(() => {
51+
// NOTE: This is a bogus URL and will not be used in the actual fetch handler.
52+
// please see the src/index.ts file for the actual fetch handler.
53+
miniOxygen
54+
.dispatchFetch('https://localhost:8000' as any)
55+
.then((d) => d.json() as Promise<any>)
56+
.then(({ flagValue, flagKey }) => {
57+
console.clear();
58+
printValueAndBanner(flagKey, flagValue);
59+
console.log('Press "q" or Ctrl+C to quit...');
60+
})
61+
.catch((err) => {
62+
console.log('Error dispatching fetch:', err.message);
63+
console.log('Press "q" or Ctrl+C to quit...');
64+
});
65+
}, 1000);
66+
67+
// Handle keypresses for cleanup
68+
process.stdin.setRawMode(true);
69+
process.stdin.resume();
70+
process.stdin.setEncoding('utf8');
71+
72+
process.stdin.on('data', async (key: string) => {
73+
// Handle Ctrl+C
74+
if (key === '\u0003') {
75+
clearInterval(interval);
76+
await miniOxygen.dispose();
77+
process.exit();
78+
}
79+
80+
// Handle 'q' key
81+
if (key === 'q' || key === 'Q') {
82+
clearInterval(interval);
83+
await miniOxygen.dispose();
84+
process.exit();
85+
}
86+
});
87+
});
88+
};
89+
90+
main().catch(console.error);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "shopify-oxygen-sdk-example",
3+
"packageManager": "yarn@3.4.1",
4+
"scripts": {
5+
"build": "tsup",
6+
"clean": "rm -rf dist",
7+
"start": "yarn clean && yarn build && ts-node app.ts"
8+
},
9+
"type": "module",
10+
"dependencies": {
11+
"@launchdarkly/shopify-oxygen-sdk": "*",
12+
"@shopify/mini-oxygen": "^4.0.0",
13+
"ts-node": "^10.9.2",
14+
"typescript": "^5.9.3"
15+
},
16+
"devDependencies": {
17+
"tsup": "^8.5.1"
18+
}
19+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { init } from '@launchdarkly/shopify-oxygen-sdk';
2+
3+
// Set sdkKey to your LaunchDarkly SDK key.
4+
const sdkKey = 'sample-sdk-key';
5+
6+
// Set featureFlagKey to the feature flag key you want to evaluate.
7+
const flagKey = 'sample-feature';
8+
9+
const context = {
10+
kind: 'user',
11+
key: 'example-user-key',
12+
name: 'Sandy',
13+
};
14+
15+
const sdkOptions = {
16+
// See the README.md file for more information on the options.
17+
};
18+
19+
export default {
20+
async fetch() {
21+
const ldClient = await init(sdkKey, sdkOptions);
22+
await ldClient.waitForInitialization({ timeout: 10 });
23+
const flagValue = await ldClient.variation(flagKey, context, false);
24+
25+
// Flush events and close the client
26+
await ldClient.flush();
27+
ldClient.close();
28+
29+
return new Response(JSON.stringify({ flagKey, flagValue }), { status: 200 });
30+
},
31+
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"compilerOptions": {
3+
"allowSyntheticDefaultImports": true,
4+
"declaration": true,
5+
"declarationMap": true,
6+
"lib": ["es6"],
7+
"module": "es2022",
8+
"moduleResolution": "node",
9+
"noImplicitOverride": true,
10+
"outDir": "dist",
11+
"resolveJsonModule": true,
12+
"rootDir": ".",
13+
"skipLibCheck": true,
14+
"sourceMap": true,
15+
"strict": true,
16+
"stripInternal": true,
17+
"target": "ES2022",
18+
},
19+
"exclude": ["tsup.config.ts"]
20+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// It is a dev dependency and the linter doesn't understand.
2+
// @ts-ignore - tsup is a dev dependency installed at runtime
3+
// eslint-disable-next-line import/no-extraneous-dependencies
4+
import { defineConfig } from 'tsup';
5+
6+
export default defineConfig({
7+
entry: {
8+
index: 'src/index.ts',
9+
},
10+
minify: true,
11+
format: ['esm'],
12+
splitting: false,
13+
clean: true,
14+
noExternal: ['@launchdarkly/shopify-oxygen-sdk'],
15+
dts: true,
16+
});

0 commit comments

Comments
 (0)