@pie-players/pie-calculator-desmos
v0.3.29
Published
Desmos calculator provider for PIE Assessment Toolkit - High-quality graphing calculators
Readme
@pie-players/pie-calculator-desmos
Desmos calculator provider for PIE Players - Premium graphing, scientific, and basic calculators.
Features
- ✅ Beautiful, intuitive graphing calculators
- ✅ Interactive expression lists
- ✅ Scientific and basic calculator modes
- ✅ State persistence and export
- ⚠️ Requires Desmos API key from desmos.com/api
- ⚠️ Requires internet connection
Installation
npm install @pie-players/pie-calculator-desmosHow Desmos API Keys Work
According to Desmos documentation, the API key should be included when loading the Desmos calculator library:
<script src="https://www.desmos.com/api/v1.11/calculator.js?apiKey=YOUR_KEY"></script>However, this approach exposes your API key in client-side HTML, which is a security risk for production applications.
Security Best Practices
⚠️ Important Security Considerations
While Desmos's documentation shows the API key embedded in the script URL (client-side), this is NOT SECURE for production because:
- Anyone can view your HTML source and see the API key
- The key can be copied and used by others
- You cannot rotate keys without redeploying your entire application
- You have no control over who uses your key
Our Recommended Patterns
This package supports three configuration patterns:
1. Development Mode (Direct API Key) - Testing Only
Use the demo key or your own key for local development:
<!-- Load Desmos with demo key -->
<script src="https://www.desmos.com/api/v1.11/calculator.js?apiKey=REDACTED_API_KEY"></script>import { DesmosCalculatorProvider } from '@pie-players/pie-calculator-desmos';
const provider = new DesmosCalculatorProvider();
await provider.initialize(); // Uses the globally loaded Desmos⚠️ Only use your real API key like this during development!
2. Production Mode (Server-Side Proxy) - ✅ RECOMMENDED
For production, use a server-side proxy to keep your API key secure:
const provider = new DesmosCalculatorProvider();
await provider.initialize({
proxyEndpoint: '/api/desmos/script-url' // Server returns the script URL with key
});Your server endpoint returns a signed or time-limited URL.
3. Pre-loaded Library (Client-Side)
If you must use client-side loading in production (not recommended), at least load the library yourself and don't pass the key through our package:
<script src="https://www.desmos.com/api/v1.11/calculator.js?apiKey=YOUR_KEY"></script>const provider = new DesmosCalculatorProvider();
await provider.initialize(); // No key needed, uses window.DesmosNote: This still exposes your key in HTML, but at least it's not in your JavaScript bundle.
Server-Side Proxy Implementation
Understanding the Challenge
Desmos requires the API key in the script URL when loading the library. To keep your key secure while still working within Desmos's architecture, you need a server-side proxy.
Option A: Proxy the Desmos Script (Most Secure)
Create a server endpoint that proxies the Desmos calculator script with your API key:
Express.js Example
// server.js
app.get('/api/desmos/calculator.js', requireAuth, async (req, res) => {
if (!req.user) {
return res.status(401).json({ error: 'Unauthorized' });
}
// Fetch Desmos script with your API key server-side
const desmosUrl = `https://www.desmos.com/api/v1.11/calculator.js?apiKey=${process.env.DESMOS_API_KEY}`;
const response = await fetch(desmosUrl);
const script = await response.text();
res.setHeader('Content-Type', 'application/javascript');
res.send(script);
});Then load from your proxy in the client:
<script src="/api/desmos/calculator.js"></script>Option B: Return Signed/Time-Limited URL
Create temporary, authenticated URLs that expire:
Next.js API Route Example
// pages/api/desmos/script-url.ts
import { getServerSession } from 'next-auth';
import { sign } from 'jsonwebtoken';
export default async function handler(req, res) {
const session = await getServerSession(req, res);
if (!session) {
return res.status(401).json({ error: 'Unauthorized' });
}
// Create a time-limited token
const token = sign(
{ userId: session.user.id },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
);
// Return URL with your API key (only valid for this session)
res.json({
scriptUrl: `https://www.desmos.com/api/v1.11/calculator.js?apiKey=${process.env.DESMOS_API_KEY}`,
expiresAt: Date.now() + 3600000
});
}Advantages of Server-Side Proxy
- Security: API key never exposed to client in retrievable form
- Authentication: Control who can access Desmos
- Rate Limiting: Implement usage limits server-side
- Usage Tracking: Monitor calculator usage for billing
- Key Rotation: Change keys without redeploying client code
- Compliance: Meets security requirements for sensitive data
Reality Check
Important: Even with a proxy, if the client loads the Desmos script, a determined user could still inspect network traffic and find the API key embedded in the script content. For true security:
- Consider if Desmos calculators are necessary for your use case
- Use provider-driven fallback strategies when a licensed graphing calculator is not required
- Contact Desmos at [email protected] to discuss enterprise security options
- Implement rate limiting and usage monitoring to detect key misuse
Usage
Basic Calculator
const provider = new DesmosCalculatorProvider();
await provider.initialize({ proxyEndpoint: '/api/desmos/token' });
const calculator = await provider.createCalculator(
'basic',
document.getElementById('calculator-container')
);Scientific Calculator
const calculator = await provider.createCalculator(
'scientific',
document.getElementById('calculator-container'),
{
desmos: {
degreeMode: true,
functionDefinition: true
}
}
);Graphing Calculator
const calculator = await provider.createCalculator(
'graphing',
document.getElementById('calculator-container'),
{
desmos: {
expressions: true,
settingsMenu: true,
zoomButtons: true,
plotInequalities: true
}
}
);Restricted/Test Mode
For assessments, you can restrict calculator features:
const calculator = await provider.createCalculator(
'graphing',
container,
{
restrictedMode: true, // Disables settings, zoom, expressions topbar
desmos: {
restrictedFunctions: true // Additional Desmos restrictions
}
}
);Configuration Options
See the DesmosCalculatorConfig interface in @pie-players/pie-calculator for all available options.
Common options:
expressions: Show/hide expression list (graphing)settingsMenu: Show/hide settings menuzoomButtons: Show/hide zoom controlsdegreeMode: Use degrees instead of radiansborder: Show calculator borderlinks: Enable links to Desmos.com
State Management
Save and restore calculator state:
// Export state
const state = calculator.exportState();
localStorage.setItem('calculator-state', JSON.stringify(state));
// Import state
const savedState = JSON.parse(localStorage.getItem('calculator-state'));
calculator.importState(savedState);Loading Desmos API
The Desmos API must be loaded before initializing the provider. You can load it from CDN:
<script src="https://www.desmos.com/api/v1.10/calculator.js?apiKey=REDACTED_API_KEY"></script>Or load it dynamically in your application.
License
This package is MIT licensed. The Desmos API requires a separate API key from Desmos.
