Skip to content

Commit

Permalink
Create external api
Browse files Browse the repository at this point in the history
  • Loading branch information
Williangalvani committed Dec 17, 2024
1 parent 999316f commit cfb0f4a
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 2 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"serve": "vite preview",
"test:ci": "vitest --coverage --run",
"test:unit": "vitest",
"typecheck": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false"
"typecheck": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
"build:lib": "BUILD_MODE=library vite build"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.4.0",
Expand Down
43 changes: 43 additions & 0 deletions src/libs/external-api/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { CallbackRateLimiter } from './callback-rate-limiter'

/**
* Current version of the Cockpit Widget API
*/
export const COCKPIT_WIDGET_API_VERSION = '0.0.0'

/**
* Listens to updates for a specific datalake variable.
* This function sets up a message listener that receives updates from the parent window
* and forwards them to the callback function, respecting the specified rate limit.
* @param {string} variable - The name of the datalake variable to listen to
* @param {Function} callback - The function to call when the variable is updated
* @param {number} maxRateHz - The maximum rate (in Hz) at which updates should be received. Default is 10 Hz
* @example
* ```typescript
* // Listen to updates at 5Hz
* listenToDatalakeVariable('temperature', (value) => {
* console.log('Temperature:', value);
* }, 5);
* ```
*/
export function listenToDatalakeVariable(variable: string, callback: (data: any) => void, maxRateHz = 10): void {
// Convert Hz to minimum interval in milliseconds
const minIntervalMs = 1000 / maxRateHz
const rateLimiter = new CallbackRateLimiter(minIntervalMs)

const message = {
type: 'cockpit:listenToDatalakeVariables',
variable: variable,
maxRateHz: maxRateHz,
}
window.parent.postMessage(message, '*')

window.addEventListener('message', function handler(event) {
if (event.data.type === 'cockpit:datalakeVariable' && event.data.variable === variable) {
// Only call callback if we haven't exceeded the rate limit
if (rateLimiter.canCall(variable)) {
callback(event.data.value)
}
}
})
}
30 changes: 30 additions & 0 deletions src/libs/external-api/callback-rate-limiter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* A simple rate limiter for callbacks that ensures a minimum time interval between calls
*/
export class CallbackRateLimiter {
private lastCallTimes = new Map<string, number>()

/**
* Creates a new CallbackRateLimiter
* @param {number} minIntervalMs - The minimum time (in milliseconds) that must pass between calls
*/
constructor(private minIntervalMs: number) {}

/**
* Checks if enough time has passed to allow another call
* @param {string} key - Unique identifier for the callback being rate limited
* @returns {boolean} true if enough time has passed since the last call, false otherwise
*/
public canCall(key: string): boolean {
const now = Date.now()
const lastCall = this.lastCallTimes.get(key) || 0
const timeSinceLastCall = now - lastCall

if (timeSinceLastCall >= this.minIntervalMs) {
this.lastCallTimes.set(key, now)
return true
}

return false
}
}
48 changes: 47 additions & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import { getVersion } from './src/libs/non-browser-utils'
// Check if we're running in Electron mode or building the application
const isElectron = process.env.ELECTRON === 'true'
const isBuilding = process.argv.includes('build')
const isLibrary = process.env.BUILD_MODE === 'library'

export default defineConfig({
// Base configuration that will be merged
const baseConfig = {
plugins: [
(isElectron || isBuilding) &&
electron([
Expand Down Expand Up @@ -70,4 +72,48 @@ export default defineConfig({
server: {
host: '0.0.0.0',
},
}

// Library-specific configuration
const libraryConfig = {
build: {
lib: {
entry: path.resolve(__dirname, 'src/libs/external-api/api.ts'),
name: 'CockpitAPI',
formats: ['es', 'umd', 'iife'],
fileName: (format: string) => {
switch (format) {
case 'iife':
return 'cockpit-external-api.browser.js'
case 'umd':
return 'cockpit-external-api.umd.js'
default:
return `cockpit-external-api.${format}.js`
}
},
},
rollupOptions: {
external: ['vue', 'vuetify'],
output: {
globals: {
vue: 'Vue',
vuetify: 'Vuetify',
},
},
},
outDir: 'dist/lib', // Separate output directory for library builds
minify: false, // Disable minification for now
},
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export default defineConfig((_configEnv) => {
if (isLibrary) {
// For library builds, merge the base config with library-specific settings
return {
...baseConfig,
...libraryConfig,
} as any
}
return baseConfig as any
})

0 comments on commit cfb0f4a

Please sign in to comment.