Skip to content

Commit efc220b

Browse files
committed
feat(naga-explorer): migrate naga-explorer app into the monorepo
1 parent 5df9672 commit efc220b

File tree

103 files changed

+23986
-10237
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+23986
-10237
lines changed

.dockerignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,8 @@ out
2626

2727
# allow lit-login-server build output for docker image
2828
!dist/apps/lit-login-server/**
29-
!dist/apps/lit-login-server
29+
!dist/apps/lit-login-server
30+
31+
# allow explorer build output for docker image
32+
!apps/explorer/dist/**
33+
!apps/explorer/dist

.eslintrc.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"root": true,
33
"ignorePatterns": ["**/*"],
4-
"plugins": ["@nrwl/nx", "import"],
4+
"plugins": ["@nx", "import"],
55
"overrides": [
66
{
77
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
88
"rules": {
9-
"@nrwl/nx/enforce-module-boundaries": [
9+
"@nx/enforce-module-boundaries": [
1010
"error",
1111
{
1212
"enforceBuildableLibDependency": true,
@@ -23,14 +23,14 @@
2323
},
2424
{
2525
"files": ["*.ts", "*.tsx"],
26-
"extends": ["plugin:@nrwl/nx/typescript"],
26+
"extends": ["plugin:@nx/typescript"],
2727
"rules": {
2828
"@typescript-eslint/no-inferrable-types": "off"
2929
}
3030
},
3131
{
3232
"files": ["*.js", "*.jsx"],
33-
"extends": ["plugin:@nrwl/nx/javascript"],
33+
"extends": ["plugin:@nx/javascript"],
3434
"rules": {}
3535
}
3636
],

apps/explorer/.eslintrc.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"extends": ["../../.eslintrc.json"],
3+
"ignorePatterns": ["!**/*"],
4+
"overrides": [
5+
{
6+
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7+
"rules": {}
8+
}
9+
]
10+
}

apps/explorer/.gitignore

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?
25+
.vercel
26+
.cursor
27+
.env
28+
.plan

apps/explorer/Dockerfile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# This file is generated by Nx.
2+
#
3+
# Build the docker image with `pnpm nx run explorer:docker-build`.
4+
# Tip: Modify "docker-build" options in project.json to change docker build args.
5+
#
6+
# Run the container with `docker run -p 4173:80 -t explorer`.
7+
FROM --platform=linux/amd64 docker.io/nginx:alpine
8+
9+
ENV NODE_ENV=production
10+
11+
# Remove default nginx site content
12+
RUN rm -rf /usr/share/nginx/html/*
13+
14+
# Copy SPA routing config
15+
COPY apps/explorer/nginx.conf /etc/nginx/conf.d/default.conf
16+
17+
# Copy the static assets produced by `nx run explorer:build`
18+
COPY apps/explorer/dist /usr/share/nginx/html
19+
20+
EXPOSE 80
21+
CMD ["nginx", "-g", "daemon off;"]

apps/explorer/README.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Lit Explorer Naga
2+
3+
Lit Explorer Naga is an application that allows you to authenticate with Lit Protocol using the native Lit auth methods.
4+
5+
# Env vars
6+
7+
```bash
8+
# Global Settings
9+
VITE_LOGIN_SERVICE_URL=https://login.litgateway.com
10+
VITE_LOGIN_DISCORD_CLIENT_ID=1052874239658692668
11+
12+
# Network-Specific Auth Service URLs
13+
VITE_AUTH_SERVICE_URL_NAGA_DEV=https://naga-dev-auth-service.getlit.dev
14+
VITE_AUTH_SERVICE_URL_NAGA_TEST=https://naga-test-auth-service.getlit.dev
15+
VITE_AUTH_SERVICE_URL_NAGA=https://naga-auth-service.getlit.dev
16+
```
17+
18+
## Getting started
19+
20+
```
21+
pnpm install
22+
pnpm nx run explorer:dev
23+
```
24+
25+
## Docker
26+
27+
To produce a deployable container:
28+
29+
```
30+
pnpm nx run explorer:build
31+
pnpm nx run explorer:docker-build
32+
docker run -p 4173:80 explorer
33+
```
34+
35+
The image serves the built assets via Nginx and includes SPA routing so client-side navigation works.
36+
37+
## Adding Lit Action examples
38+
39+
- Add a new file in `src/lit-action-examples/entries/` that default-exports a `LitActionExample`. The `id` must be unique.
40+
- Use `String.raw` to define multiline snippets, e.g. ``const code = String.raw\`...\`;`` and fill in `title`, optional `description`, `order`, and any default `jsParams`.
41+
- The registry auto-loads every file in that directory, so your example will appear in the Lit Action editor once you save and refresh the app.
42+
- Prefer small, focused samples that demonstrate a single concept; link to docs inside the description if extra context is needed.
43+
44+
## FAQs
45+
46+
### What "logged-in" means here
47+
48+
- You are considered "logged-in" when both a PKP and an auth context exist in state.
49+
50+
### How you become "logged-in"
51+
52+
After authenticating with a method (Google, Discord, WebAuthn, EOA, Stytch, Custom), either:
53+
54+
- You select an existing PKP in the PKP selection section
55+
- You mint a new PKP and immediately create `authContext`, then set `user`
56+
57+
### What redirect happens and when
58+
59+
The `<LitAuthProvider />` does not redirect on successful login. It simply closes the modal once user is set and isAuthenticated becomes true.
60+
61+
The dashboard is always the index route for `/`, and it conditionally renders based on auth state from context. When the user logs in, React re-renders the same component with different UI.
62+
63+
Inside `LoggedInDashboard`, it reads user from `useLitAuth()`. If there’s no user, it shows a sign-in experience and, in popup mode, auto-opens the modal.
64+
65+
# Screenshots
66+
67+
## Login Modal
68+
69+
![Login Modal](./public/screenshot-1.png)
70+
71+
## Logged in Dashboard
72+
![Logged in Dashboard](./public/screenshot-2.png)

apps/explorer/check-deps.js

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* Dependency Checker Script
5+
*
6+
* This script scans node_modules for missing dependencies that could cause
7+
* "Failed to resolve module specifier" errors in production builds.
8+
*
9+
* Usage: node check-deps.js
10+
*/
11+
12+
import fs from 'fs';
13+
import path from 'path';
14+
import { execSync } from 'child_process';
15+
import { fileURLToPath } from 'url';
16+
17+
const __filename = fileURLToPath(import.meta.url);
18+
const __dirname = path.dirname(__filename);
19+
20+
console.log('🔍 Scanning for missing dependencies...\n');
21+
22+
// Read current package.json
23+
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
24+
const currentDeps = {
25+
...packageJson.dependencies || {},
26+
...packageJson.devDependencies || {}
27+
};
28+
29+
// Function to extract require/import statements
30+
function extractDependencies(filePath) {
31+
try {
32+
const content = fs.readFileSync(filePath, 'utf8');
33+
const requireMatches = content.match(/require\(["']([^"']+)["']\)/g) || [];
34+
const importMatches = content.match(/import\s+.*?\s+from\s+["']([^"']+)["']/g) || [];
35+
36+
const deps = new Set();
37+
38+
// Extract require dependencies
39+
requireMatches.forEach(match => {
40+
const dep = match.match(/require\(["']([^"']+)["']\)/)[1];
41+
if (!dep.startsWith('.') && !dep.startsWith('/')) {
42+
// Get package name (handle scoped packages)
43+
const packageName = dep.startsWith('@')
44+
? dep.split('/').slice(0, 2).join('/')
45+
: dep.split('/')[0];
46+
deps.add(packageName);
47+
}
48+
});
49+
50+
// Extract import dependencies
51+
importMatches.forEach(match => {
52+
const dep = match.match(/from\s+["']([^"']+)["']/)[1];
53+
if (!dep.startsWith('.') && !dep.startsWith('/')) {
54+
const packageName = dep.startsWith('@')
55+
? dep.split('/').slice(0, 2).join('/')
56+
: dep.split('/')[0];
57+
deps.add(packageName);
58+
}
59+
});
60+
61+
return Array.from(deps);
62+
} catch (error) {
63+
return [];
64+
}
65+
}
66+
67+
// Function to scan directory recursively
68+
function scanDirectory(dir, extensions = ['.js', '.ts', '.tsx', '.jsx']) {
69+
const allDeps = new Set();
70+
71+
function scanRecursive(currentDir) {
72+
try {
73+
const items = fs.readdirSync(currentDir);
74+
75+
for (const item of items) {
76+
const fullPath = path.join(currentDir, item);
77+
const stat = fs.statSync(fullPath);
78+
79+
if (stat.isDirectory() && !item.startsWith('.') && item !== 'node_modules') {
80+
scanRecursive(fullPath);
81+
} else if (stat.isFile() && extensions.some(ext => item.endsWith(ext))) {
82+
const deps = extractDependencies(fullPath);
83+
deps.forEach(dep => allDeps.add(dep));
84+
}
85+
}
86+
} catch (error) {
87+
// Skip directories we can't read
88+
}
89+
}
90+
91+
scanRecursive(dir);
92+
return Array.from(allDeps);
93+
}
94+
95+
// Scan specific directories for dependencies
96+
const directories = [
97+
'node_modules/@lit-protocol',
98+
'src'
99+
];
100+
101+
const allFoundDeps = new Set();
102+
103+
directories.forEach(dir => {
104+
if (fs.existsSync(dir)) {
105+
console.log(`📁 Scanning ${dir}...`);
106+
const deps = scanDirectory(dir);
107+
deps.forEach(dep => allFoundDeps.add(dep));
108+
}
109+
});
110+
111+
// Filter out built-in Node.js modules and current dependencies
112+
const builtInModules = new Set([
113+
'fs', 'path', 'crypto', 'stream', 'buffer', 'util', 'events', 'os', 'url',
114+
'http', 'https', 'querystring', 'zlib', 'worker_threads', 'fs/promises'
115+
]);
116+
117+
const missingDeps = Array.from(allFoundDeps).filter(dep =>
118+
!currentDeps[dep] &&
119+
!builtInModules.has(dep) &&
120+
dep !== 'react' && // Common false positives
121+
dep !== 'node_modules'
122+
);
123+
124+
console.log('\n📊 Results:');
125+
console.log(`Total dependencies found: ${allFoundDeps.size}`);
126+
console.log(`Missing dependencies: ${missingDeps.length}`);
127+
128+
if (missingDeps.length > 0) {
129+
console.log('\n❌ Missing Dependencies:');
130+
console.log('Add these to your package.json:\n');
131+
132+
const suggestions = {};
133+
134+
// Common version suggestions
135+
const versionMap = {
136+
'siwe': '^2.3.2',
137+
'siwe-recap': '^0.0.2-alpha.0',
138+
'jose': '^4.14.4',
139+
'ethers': '5.7.2',
140+
'viem': '^2.29.4',
141+
'@noble/curves': '^1.2.0',
142+
'@noble/hashes': '^1.3.0',
143+
'base64url': '^3.0.1',
144+
'cbor-web': '^9.0.2',
145+
'elysia': '^1.2.25',
146+
'tslib': '^2.3.0',
147+
'zod-validation-error': '^3.4.0',
148+
'@openagenda/verror': '^3.1.4',
149+
'@simplewebauthn/browser': '^7.2.0'
150+
};
151+
152+
missingDeps.forEach(dep => {
153+
const version = versionMap[dep] || '^latest';
154+
suggestions[dep] = version;
155+
console.log(` "${dep}": "${version}",`);
156+
});
157+
158+
console.log('\n💡 Or run this command to install them all:');
159+
const installCmd = `pnpm add ${missingDeps.map(dep => `${dep}@${versionMap[dep] || 'latest'}`).join(' ')}`;
160+
console.log(`\n${installCmd}\n`);
161+
162+
} else {
163+
console.log('\n✅ All dependencies appear to be present!');
164+
}
165+
166+
console.log('\n🔧 Current package.json dependencies:');
167+
Object.keys(currentDeps).sort().forEach(dep => {
168+
console.log(` ${dep}: ${currentDeps[dep]}`);
169+
});

0 commit comments

Comments
 (0)