From dafcb05f08f1ee48de27b02a964b38d363a45f95 Mon Sep 17 00:00:00 2001 From: Tyler Nix Date: Wed, 17 Sep 2025 16:11:59 -0600 Subject: [PATCH] Add ConfigValue component for dynamic configuration values - Create ConfigValue React component with TypeScript support - Auto-generates product-config.ts from OpenFGA schema - Provides type-safe configuration value display in MDX - Enhanced update-config-page.mjs to generate generic product-config.ts - Enables multi-tenant documentation with different config values --- scripts/update-config-page.mjs | 137 +++- src/components/Docs/ConfigValue/index.tsx | 49 ++ src/components/Docs/index.ts | 1 + src/constants/product-config.ts | 725 ++++++++++++++++++++++ 4 files changed, 909 insertions(+), 3 deletions(-) create mode 100644 src/components/Docs/ConfigValue/index.tsx create mode 100644 src/constants/product-config.ts diff --git a/scripts/update-config-page.mjs b/scripts/update-config-page.mjs index 2835482d7e..4ee43ba978 100644 --- a/scripts/update-config-page.mjs +++ b/scripts/update-config-page.mjs @@ -1,5 +1,6 @@ import https from 'node:https'; import fs from 'node:fs/promises'; +import { execSync } from 'node:child_process'; /** * Resolves a reference to an internal schema - external references are not supported @@ -62,6 +63,50 @@ function parseValue(type, value) { } } +/** + * Extracts configuration constants from the schema + * @param properties + * @param jsonData + * @param parentKey + * @returns {Promise} + */ +async function extractConstants(properties, jsonData, parentKey = '') { + let constants = {}; + + for (const [key, value] of Object.entries(properties)) { + if (value.$ref) { + const refSchema = await resolveRef(value.$ref, jsonData); + const nestedConstants = await extractConstants(refSchema.properties, jsonData, parentKey ? `${parentKey}.${key}` : key); + constants = { ...constants, ...nestedConstants }; + } else { + const fullKey = parentKey ? `${parentKey}.${key}` : key; + + // Only include constants that have default values or are arrays (which can default to empty array) + if (value.type !== 'object' && (value.default !== undefined || value.type === 'array')) { + // Convert config key to constant name (e.g., maxTuplesPerWrite -> MAX_TUPLES_PER_WRITE) + const constantName = fullKey + .replace(/\./g, '_') + .replace(/([a-z])([A-Z])/g, '$1_$2') + .toUpperCase(); + + constants[constantName] = { + value: value.default !== undefined ? value.default : (value.type === 'array' ? [] : null), + type: value.type, + description: value.description || '', + configKey: fullKey + }; + } + + if (value.type === 'object' && value.properties) { + const nestedConstants = await extractConstants(value.properties, jsonData, fullKey); + constants = { ...constants, ...nestedConstants }; + } + } + } + + return constants; +} + /** * Processes the properties of a schema and returns the MDX content * @param properties @@ -97,6 +142,72 @@ async function processProperties(properties, jsonData, parentKey = '') { return mdxContent; } +/** + * Generates a TypeScript constants file from the extracted constants + * @param constants + * @param releaseData + * @returns {string} + */ +function generateConstantsFile(constants, releaseData) { + let content = `// Auto-generated product configuration constants +// Generated from ${releaseData.release} config schema +// Do not edit this file manually - it will be overwritten + +/** + * Product Configuration Default Values + * + * These constants are extracted from the ${releaseData.release} configuration schema. + * They represent the default values for various configuration options. + */ + +`; + + // Sort constants by name for consistency + const sortedConstants = Object.entries(constants).sort(([a], [b]) => a.localeCompare(b)); + + for (const [constantName, config] of sortedConstants) { + // Add JSDoc comment with description and config key + content += `/**\n`; + content += ` * ${config.description || 'Configuration option'}\n`; + content += ` * Config key: ${config.configKey}\n`; + content += ` * Type: ${config.type}\n`; + content += ` */\n`; + + // Generate the constant declaration + if (config.type === 'string') { + content += `export const ${constantName} = '${config.value}';\n\n`; + } else if (config.type === 'boolean') { + content += `export const ${constantName} = ${config.value};\n\n`; + } else if (config.type === 'array') { + // Handle array values - use empty array if no default + const arrayValue = Array.isArray(config.value) ? JSON.stringify(config.value) : '[]'; + content += `export const ${constantName} = ${arrayValue};\n\n`; + } else { + content += `export const ${constantName} = ${config.value};\n\n`; + } + } + + // Add a convenience object with all constants + content += `/**\n`; + content += ` * All product configuration default values in a single object\n`; + content += ` */\n`; + content += `export const PRODUCT_CONFIG_DEFAULTS = {\n`; + + for (const [constantName] of sortedConstants) { + content += ` ${constantName},\n`; + } + + content += `} as const;\n\n`; + + // Add type definitions + content += `/**\n`; + content += ` * Type representing all available product configuration constants\n`; + content += ` */\n`; + content += `export type ProductConfigConstants = typeof PRODUCT_CONFIG_DEFAULTS;\n`; + + return content; +} + /** * Generates the MDX content for the .config-schema.json file * @param releaseData {release: string, url: string, releaseUrl: string} @@ -295,21 +406,41 @@ async function getFileData() { } const OUTPUT_FILE = 'docs/content/getting-started/setup-openfga/configuration.mdx'; +const CONSTANTS_OUTPUT_FILE = 'src/constants/product-config.ts'; + /** - * Downloads the .config-schema for the latest release of OpenFGA and generates the MDX content for it + * Downloads the .config-schema for the latest release of OpenFGA and generates the MDX content and constants file * @returns {Promise<{release: string, url: string, releaseUrl: string}>} */ async function generateMdxForLatestRelease() { const releaseData = await getFileData(); const jsonData = await performHttpRequest(releaseData.url); + + // Generate the MDX content const mdxContent = await getMdxContent(releaseData, jsonData); - await fs.writeFile(OUTPUT_FILE, mdxContent, 'utf8'); + + // Extract constants and generate constants file + if (jsonData.properties) { + const constants = await extractConstants(jsonData.properties, jsonData); + const constantsContent = generateConstantsFile(constants, releaseData); + + // Ensure the constants directory exists + await fs.mkdir('src/constants', { recursive: true }); + await fs.writeFile(CONSTANTS_OUTPUT_FILE, constantsContent, 'utf8'); + + // Format the generated constants file with Prettier + try { + execSync(`npx prettier --write ${CONSTANTS_OUTPUT_FILE}`, { stdio: 'inherit' }); + } catch (error) { + console.warn(`Warning: Could not format ${CONSTANTS_OUTPUT_FILE} with Prettier:`, error.message); + } + } return releaseData; } generateMdxForLatestRelease() - .then(({ release, url }) => console.log(`Downloaded .config-schema.json file for ${release} from ${url} and saved the generated file at ${OUTPUT_FILE}`)) + .then(({ release, url }) => console.log(`Downloaded .config-schema.json file for ${release} from ${url} and saved the generated files at ${OUTPUT_FILE} and ${CONSTANTS_OUTPUT_FILE}`)) .catch(console.error); \ No newline at end of file diff --git a/src/components/Docs/ConfigValue/index.tsx b/src/components/Docs/ConfigValue/index.tsx new file mode 100644 index 0000000000..33bb6b6707 --- /dev/null +++ b/src/components/Docs/ConfigValue/index.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import * as ProductConfig from '../../../constants/product-config'; + +// Type for config constants +type ConfigConstants = keyof typeof ProductConfig.PRODUCT_CONFIG_DEFAULTS; + +interface ConfigValueProps { + /** + * The name of the configuration constant to display + * Should match the exported constant name from product-config.ts + */ + name: ConfigConstants; + + /** + * Optional format for the value display + */ + format?: 'code' | 'text'; +} + +/** + * Component to display product configuration default values + * + * This component fetches configuration values from the product-config.ts file, + * which can be auto-generated (for OpenFGA) or manually maintained (for other products). + * This ensures the documentation stays synchronized with the actual configuration schema. + * + * @example + * ```mdx + * The Write API allows up to tuples per request. + * ``` + */ +export const ConfigValue: React.FC = ({ name, format = 'code' }) => { + const value = ProductConfig.PRODUCT_CONFIG_DEFAULTS[name]; + + if (value === undefined) { + console.warn(`ConfigValue: Unknown configuration constant "${String(name)}"`); + return [Unknown config: {String(name)}]; + } + + const displayValue = String(value); + + if (format === 'code') { + return {displayValue}; + } + + return {displayValue}; +}; + +export default ConfigValue; diff --git a/src/components/Docs/index.ts b/src/components/Docs/index.ts index 676d8b02ff..cdd5a18def 100644 --- a/src/components/Docs/index.ts +++ b/src/components/Docs/index.ts @@ -2,6 +2,7 @@ export * from './AuthorizationModel'; export * from './Banner'; export * from './CardBox'; export * from './Column'; +export * from './ConfigValue'; export * from './DocumentationNotice'; export * from './Feedback'; export * from './Overview'; diff --git a/src/constants/product-config.ts b/src/constants/product-config.ts new file mode 100644 index 0000000000..450b3a0667 --- /dev/null +++ b/src/constants/product-config.ts @@ -0,0 +1,725 @@ +// Auto-generated product configuration constants +// Generated from v1.10.0 config schema +// Do not edit this file manually - it will be overwritten + +/** + * Product Configuration Default Values + * + * These constants are extracted from the v1.10.0 configuration schema. + * They represent the default values for various configuration options. + */ + +/** + * Enable/disable the access control store. + * Config key: accessControl.enabled + * Type: boolean + */ +export const ACCESS_CONTROL_ENABLED = false; + +/** + * The modelId to be used for the access control store. + * Config key: accessControl.modelId + * Type: string + */ +export const ACCESS_CONTROL_MODEL_ID = ''; + +/** + * The storeId to be used for the access control store. + * Config key: accessControl.storeId + * Type: string + */ +export const ACCESS_CONTROL_STORE_ID = ''; + +/** + * The authentication method to use. + * Config key: authn.method + * Type: string + */ +export const AUTHN_METHOD = 'none'; + +/** + * the OIDC client id claims that will be used to parse the clientID - configure in order of priority (first is highest). Defaults to [`azp`, `client_id`] + * Config key: authn.oidc.clientIdClaims + * Type: array + */ +export const AUTHN_OIDC_CLIENT_ID_CLAIMS = []; + +/** + * the OIDC issuer DNS aliases that will be accepted as valid when verifying the `iss` field of the JWTs. + * Config key: authn.oidc.issuerAliases + * Type: array + */ +export const AUTHN_OIDC_ISSUER_ALIASES = []; + +/** + * the OIDC subject names that will be accepted as valid when verifying the `sub` field of the JWTs. If empty, every `sub` will be allowed + * Config key: authn.oidc.subjects + * Type: array + */ +export const AUTHN_OIDC_SUBJECTS = []; + +/** + * List of preshared keys used for authentication + * Config key: authn.preshared.keys + * Type: array + */ +export const AUTHN_PRESHARED_KEYS = []; + +/** + * enabling dynamic invalidation of check query cache and check iterator cache based on whether there are recent tuple writes. If enabled, cache will be invalidated when either 1) there are tuples written to the store OR 2) the check query cache or check iterator cache TTL has expired. + * Config key: cacheController.enabled + * Type: boolean + */ +export const CACHE_CONTROLLER_ENABLED = false; + +/** + * if cache controller is enabled, control how frequent read changes are invoked internally to query for recent tuple writes to the store. + * Config key: cacheController.ttl + * Type: string + */ +export const CACHE_CONTROLLER_TTL = '10s'; + +/** + * The offset (in minutes) from the current time. Changes that occur after this offset will not be included in the response of ReadChanges. + * Config key: changelogHorizonOffset + * Type: integer + */ +export const CHANGELOG_HORIZON_OFFSET = 0; + +/** + * the size limit (in items) of the cache for Check (queries and iterators) + * Config key: checkCache.limit + * Type: integer + */ +export const CHECK_CACHE_LIMIT = 10000; + +/** + * enable throttling when check request's number of dispatches is high + * Config key: checkDispatchThrottling.enabled + * Type: boolean + */ +export const CHECK_DISPATCH_THROTTLING_ENABLED = false; + +/** + * the frequency period that the deprioritized throttling queue is evaluated for a check request. A higher value will result in more aggressive throttling + * Config key: checkDispatchThrottling.frequency + * Type: string + */ +export const CHECK_DISPATCH_THROTTLING_FREQUENCY = '10µs'; + +/** + * define the maximum dispatch threshold beyond above which requests will be throttled. 0 will use the 'dispatchThrottling.threshold' value as maximum + * Config key: checkDispatchThrottling.maxThreshold + * Type: integer + */ +export const CHECK_DISPATCH_THROTTLING_MAX_THRESHOLD = 0; + +/** + * define the number of recursive operations to occur before getting throttled for a check request + * Config key: checkDispatchThrottling.threshold + * Type: integer + */ +export const CHECK_DISPATCH_THROTTLING_THRESHOLD = 100; + +/** + * enable caching of datastore iterators. The key is a string representing a database query, and the value is a list of tuples. Each iterator is the result of a database query, for example usersets related to a specific object, or objects related to a specific user, up to a certain number of tuples per iterator. If the request's consistency is HIGHER_CONSISTENCY, this cache is not used. + * Config key: checkIteratorCache.enabled + * Type: boolean + */ +export const CHECK_ITERATOR_CACHE_ENABLED = false; + +/** + * if caching of datastore iterators of Check requests is enabled, this is the limit of tuples to cache per key + * Config key: checkIteratorCache.maxResults + * Type: integer + */ +export const CHECK_ITERATOR_CACHE_MAX_RESULTS = 10000; + +/** + * if caching of datastore iterators of Check requests is enabled, this is the TTL of each value + * Config key: checkIteratorCache.ttl + * Type: string + */ +export const CHECK_ITERATOR_CACHE_TTL = '10s'; + +/** + * enable caching of Check requests. The key is a string representing a query, and the value is a boolean. For example, if you have a relation `define viewer: owner or editor`, and the query is Check(user:anne, viewer, doc:1), we'll evaluate the `owner` relation and the `editor` relation and cache both results: (user:anne, viewer, doc:1) -> allowed=true and (user:anne, owner, doc:1) -> allowed=true. The cache is stored in-memory; the cached values are overwritten on every change in the result, and cleared after the configured TTL. This flag improves latency, but turns Check and ListObjects into eventually consistent APIs. If the request's consistency is HIGHER_CONSISTENCY, this cache is not used. + * Config key: checkQueryCache.enabled + * Type: boolean + */ +export const CHECK_QUERY_CACHE_ENABLED = false; + +/** + * DEPRECATED use OPENFGA_CHECK_CACHE_LIMIT. If caching of Check and ListObjects calls is enabled, this is the size limit (in items) of the cache + * Config key: checkQueryCache.limit + * Type: integer + */ +export const CHECK_QUERY_CACHE_LIMIT = 10000; + +/** + * if caching of Check and ListObjects is enabled, this is the TTL of each value + * Config key: checkQueryCache.ttl + * Type: string + */ +export const CHECK_QUERY_CACHE_TTL = '10s'; + +/** + * Propagate a requests context to the datastore implementation. Settings this parameter can result in connection pool draining on request aborts and timeouts. + * Config key: contextPropagationToDatastore + * Type: boolean + */ +export const CONTEXT_PROPAGATION_TO_DATASTORE = false; + +/** + * the maximum amount of time a connection to the datastore may be idle + * Config key: datastore.connMaxIdleTime + * Type: string + */ +export const DATASTORE_CONN_MAX_IDLE_TIME = '0s'; + +/** + * the maximum amount of time a connection to the datastore may be reused + * Config key: datastore.connMaxLifetime + * Type: string + */ +export const DATASTORE_CONN_MAX_LIFETIME = '0s'; + +/** + * The datastore engine that will be used for persistence. + * Config key: datastore.engine + * Type: string + */ +export const DATASTORE_ENGINE = 'memory'; + +/** + * The maximum number of authorization models that will be cached in memory + * Config key: datastore.maxCacheSize + * Type: integer + */ +export const DATASTORE_MAX_CACHE_SIZE = 100000; + +/** + * the maximum number of connections to the datastore in the idle connection pool. + * Config key: datastore.maxIdleConns + * Type: integer + */ +export const DATASTORE_MAX_IDLE_CONNS = 10; + +/** + * The maximum number of open connections to the datastore. + * Config key: datastore.maxOpenConns + * Type: integer + */ +export const DATASTORE_MAX_OPEN_CONNS = 30; + +/** + * enable/disable sql metrics for the datastore + * Config key: datastore.metrics.enabled + * Type: boolean + */ +export const DATASTORE_METRICS_ENABLED = false; + +/** + * a list of experimental features to enable + * Config key: experimentals + * Type: array + */ +export const EXPERIMENTALS = []; + +/** + * The host:port address to serve the grpc server on. + * Config key: grpc.addr + * Type: string + */ +export const GRPC_ADDR = '0.0.0.0:8081'; + +/** + * Enables or disables transport layer security (TLS). + * Config key: grpc.tls.enabled + * Type: boolean + */ +export const GRPC_TLS_ENABLED = false; + +/** + * The host:port address to serve the HTTP server on. + * Config key: http.addr + * Type: string + */ +export const HTTP_ADDR = '0.0.0.0:8080'; + +/** + * List of allowed headers for CORS requests + * Config key: http.corsAllowedHeaders + * Type: array + */ +export const HTTP_CORS_ALLOWED_HEADERS = ['*']; + +/** + * List of allowed origins for CORS requests + * Config key: http.corsAllowedOrigins + * Type: array + */ +export const HTTP_CORS_ALLOWED_ORIGINS = ['*']; + +/** + * Enables or disables the OpenFGA HTTP server. If this is set to true then 'grpc.enabled' must be set to true. + * Config key: http.enabled + * Type: boolean + */ +export const HTTP_ENABLED = true; + +/** + * Enables or disables transport layer security (TLS). + * Config key: http.tls.enabled + * Type: boolean + */ +export const HTTP_TLS_ENABLED = false; + +/** + * The timeout duration for proxying HTTP requests upstream to the grpc endpoint. + * Config key: http.upstreamTimeout + * Type: string + */ +export const HTTP_UPSTREAM_TIMEOUT = '3s'; + +/** + * The timeout deadline for serving ListObjects requests + * Config key: listObjectsDeadline + * Type: string + */ +export const LIST_OBJECTS_DEADLINE = '3s'; + +/** + * enable throttling when ListObjects request's number of dispatches is high + * Config key: listObjectsDispatchThrottling.enabled + * Type: boolean + */ +export const LIST_OBJECTS_DISPATCH_THROTTLING_ENABLED = false; + +/** + * the frequency period that the deprioritized throttling queue is evaluated for a ListObjects request. A higher value will result in more aggressive throttling + * Config key: listObjectsDispatchThrottling.frequency + * Type: string + */ +export const LIST_OBJECTS_DISPATCH_THROTTLING_FREQUENCY = '10µs'; + +/** + * define the maximum dispatch threshold beyond above which requests will be throttled for a ListObjects request. 0 will use the 'dispatchThrottling.threshold' value as maximum + * Config key: listObjectsDispatchThrottling.maxThreshold + * Type: integer + */ +export const LIST_OBJECTS_DISPATCH_THROTTLING_MAX_THRESHOLD = 0; + +/** + * define the number of recursive operations to occur before getting throttled for a ListObjects request + * Config key: listObjectsDispatchThrottling.threshold + * Type: integer + */ +export const LIST_OBJECTS_DISPATCH_THROTTLING_THRESHOLD = 100; + +/** + * enable caching of datastore iterators in ListObjects. The key is a string representing a database query, and the value is a list of tuples. Each iterator is the result of a database query, for example usersets related to a specific object, or objects related to a specific user, up to a certain number of tuples per iterator. If the request's consistency is HIGHER_CONSISTENCY, this cache is not used. + * Config key: listObjectsIteratorCache.enabled + * Type: boolean + */ +export const LIST_OBJECTS_ITERATOR_CACHE_ENABLED = false; + +/** + * if caching of datastore iterators of ListObjects requests is enabled, this is the limit of tuples to cache per key + * Config key: listObjectsIteratorCache.maxResults + * Type: integer + */ +export const LIST_OBJECTS_ITERATOR_CACHE_MAX_RESULTS = 10000; + +/** + * if caching of datastore iterators of ListObjects requests is enabled, this is the TTL of each value + * Config key: listObjectsIteratorCache.ttl + * Type: string + */ +export const LIST_OBJECTS_ITERATOR_CACHE_TTL = '10s'; + +/** + * The maximum results to return in the non-streaming ListObjects API response. If 0, all results can be returned + * Config key: listObjectsMaxResults + * Type: integer + */ +export const LIST_OBJECTS_MAX_RESULTS = 1000; + +/** + * The timeout deadline for serving ListUsers requests. If 0s, there is no deadline + * Config key: listUsersDeadline + * Type: string + */ +export const LIST_USERS_DEADLINE = '3s'; + +/** + * enable throttling when list users request's number of dispatches is high + * Config key: listUsersDispatchThrottling.enabled + * Type: boolean + */ +export const LIST_USERS_DISPATCH_THROTTLING_ENABLED = false; + +/** + * the frequency period that the deprioritized throttling queue is evaluated for a list users request. A higher value will result in more aggressive throttling + * Config key: listUsersDispatchThrottling.frequency + * Type: string + */ +export const LIST_USERS_DISPATCH_THROTTLING_FREQUENCY = '10µs'; + +/** + * define the maximum dispatch threshold beyond above which requests will be throttled for a list users request. 0 will use the 'dispatchThrottling.threshold' value as maximum + * Config key: listUsersDispatchThrottling.maxThreshold + * Type: integer + */ +export const LIST_USERS_DISPATCH_THROTTLING_MAX_THRESHOLD = 0; + +/** + * define the number of recursive operations to occur before getting throttled for a list users request + * Config key: listUsersDispatchThrottling.threshold + * Type: integer + */ +export const LIST_USERS_DISPATCH_THROTTLING_THRESHOLD = 100; + +/** + * The maximum results to return in ListUsers API response. If 0, all results can be returned + * Config key: listUsersMaxResults + * Type: integer + */ +export const LIST_USERS_MAX_RESULTS = 1000; + +/** + * The log format to output logs in. For production we recommend 'json' format. + * Config key: log.format + * Type: string + */ +export const LOG_FORMAT = 'text'; + +/** + * The log level to set. For production we recommend 'info' format. + * Config key: log.level + * Type: string + */ +export const LOG_LEVEL = 'info'; + +/** + * The timestamp format to use for the log output. + * Config key: log.timestampFormat + * Type: string + */ +export const LOG_TIMESTAMP_FORMAT = 'Unix'; + +/** + * The maximum size in bytes allowed for persisting an Authorization Model (default is 256KB). + * Config key: maxAuthorizationModelSizeInBytes + * Type: integer + */ +export const MAX_AUTHORIZATION_MODEL_SIZE_IN_BYTES = 262144; + +/** + * The maximum number of tuples allowed in a BatchCheck request. + * Config key: maxChecksPerBatchCheck + * Type: integer + */ +export const MAX_CHECKS_PER_BATCH_CHECK = 50; + +/** + * The maximum number of checks that can be processed concurrently in a batch check request. + * Config key: maxConcurrentChecksPerBatchCheck + * Type: integer + */ +export const MAX_CONCURRENT_CHECKS_PER_BATCH_CHECK = 50; + +/** + * The maximum allowed number of concurrent reads in a single Check query (default is MaxUint32). + * Config key: maxConcurrentReadsForCheck + * Type: integer + */ +export const MAX_CONCURRENT_READS_FOR_CHECK = 4294967295; + +/** + * The maximum allowed number of concurrent reads in a single ListObjects query (default is MaxUint32). + * Config key: maxConcurrentReadsForListObjects + * Type: integer + */ +export const MAX_CONCURRENT_READS_FOR_LIST_OBJECTS = 4294967295; + +/** + * The maximum allowed number of concurrent reads in a single ListUsers query (default is MaxUint32). + * Config key: maxConcurrentReadsForListUsers + * Type: integer + */ +export const MAX_CONCURRENT_READS_FOR_LIST_USERS = 4294967295; + +/** + * The maximum cost for CEL condition evaluation before a request returns an error (default is 100). + * Config key: maxConditionEvaluationCost + * Type: integer + */ +export const MAX_CONDITION_EVALUATION_COST = 100; + +/** + * The maximum allowed number of tuples per Write transaction. + * Config key: maxTuplesPerWrite + * Type: integer + */ +export const MAX_TUPLES_PER_WRITE = 100; + +/** + * The maximum allowed number of type definitions per authorization model. + * Config key: maxTypesPerAuthorizationModel + * Type: integer + */ +export const MAX_TYPES_PER_AUTHORIZATION_MODEL = 100; + +/** + * the host:port address to serve the prometheus metrics server on + * Config key: metrics.addr + * Type: string + */ +export const METRICS_ADDR = '0.0.0.0:2112'; + +/** + * enables prometheus histogram metrics for RPC latency distributions + * Config key: metrics.enableRPCHistograms + * Type: boolean + */ +export const METRICS_ENABLE_RPCHISTOGRAMS = false; + +/** + * enable/disable prometheus metrics on the '/metrics' endpoint + * Config key: metrics.enabled + * Type: boolean + */ +export const METRICS_ENABLED = true; + +/** + * How often the planner checks for stale keys. + * Config key: planner.cleanupInterval + * Type: string + */ +export const PLANNER_CLEANUP_INTERVAL = '0'; + +/** + * How long a planner key can be unused before being evicted. + * Config key: planner.evictionThreshold + * Type: undefined + */ +export const PLANNER_EVICTION_THRESHOLD = 0; + +/** + * The initial guess for the planners estimation. + * Config key: planner.initialGuess + * Type: string + */ +export const PLANNER_INITIAL_GUESS = '10ms'; + +/** + * Enable/disable the OpenFGA Playground. + * Config key: playground.enabled + * Type: boolean + */ +export const PLAYGROUND_ENABLED = true; + +/** + * The port to serve the local OpenFGA Playground on. + * Config key: playground.port + * Type: integer + */ +export const PLAYGROUND_PORT = 3000; + +/** + * The host:port address to serve the pprof profiler server on. + * Config key: profiler.addr + * Type: string + */ +export const PROFILER_ADDR = ':3001'; + +/** + * Enabled/disable pprof profiling. + * Config key: profiler.enabled + * Type: boolean + */ +export const PROFILER_ENABLED = false; + +/** + * Datastore query count buckets used to label the histogram metric for measuring request duration. + * Config key: requestDurationDatastoreQueryCountBuckets + * Type: array + */ +export const REQUEST_DURATION_DATASTORE_QUERY_COUNT_BUCKETS = [50, 200]; + +/** + * Dispatch count buckets used to label the histogram metric for measuring request duration. + * Config key: requestDurationDispatchCountBuckets + * Type: array + */ +export const REQUEST_DURATION_DISPATCH_COUNT_BUCKETS = [50, 200]; + +/** + * The timeout duration for a request. + * Config key: requestTimeout + * Type: string + */ +export const REQUEST_TIMEOUT = '3s'; + +/** + * Defines how many nodes on a given level can be evaluated concurrently in a Check resolution tree. + * Config key: resolveNodeBreadthLimit + * Type: integer + */ +export const RESOLVE_NODE_BREADTH_LIMIT = 10; + +/** + * Maximum resolution depth to attempt before throwing an error (defines how deeply nested an authorization model can be before a query errors out). + * Config key: resolveNodeLimit + * Type: integer + */ +export const RESOLVE_NODE_LIMIT = 25; + +/** + * enabling sharing of datastore iterators with different consumers. Each iterator is the result of a database query, for example usersets related to a specific object, or objects related to a specific user, up to a certain number of tuples per iterator. + * Config key: sharedIterator.enabled + * Type: boolean + */ +export const SHARED_ITERATOR_ENABLED = false; + +/** + * if shared-iterator-enabled is enabled, this is the limit of the number of iterators that can be shared. + * Config key: sharedIterator.limit + * Type: integer + */ +export const SHARED_ITERATOR_LIMIT = 1000000; + +/** + * Enable tracing. + * Config key: trace.enabled + * Type: boolean + */ +export const TRACE_ENABLED = false; + +/** + * The grpc endpoint of the trace collector + * Config key: trace.otlp.endpoint + * Type: string + */ +export const TRACE_OTLP_ENDPOINT = '0.0.0.0:4317'; + +/** + * Whether to use TLS connection for the trace collector + * Config key: trace.otlp.tls.enabled + * Type: boolean + */ +export const TRACE_OTLP_TLS_ENABLED = false; + +/** + * The fraction of traces to sample. 1 means all, 0 means none. + * Config key: trace.sampleRatio + * Type: number + */ +export const TRACE_SAMPLE_RATIO = 0.2; + +/** + * The service name included in sampled traces. + * Config key: trace.serviceName + * Type: string + */ +export const TRACE_SERVICE_NAME = 'openfga'; + +/** + * All product configuration default values in a single object + */ +export const PRODUCT_CONFIG_DEFAULTS = { + ACCESS_CONTROL_ENABLED, + ACCESS_CONTROL_MODEL_ID, + ACCESS_CONTROL_STORE_ID, + AUTHN_METHOD, + AUTHN_OIDC_CLIENT_ID_CLAIMS, + AUTHN_OIDC_ISSUER_ALIASES, + AUTHN_OIDC_SUBJECTS, + AUTHN_PRESHARED_KEYS, + CACHE_CONTROLLER_ENABLED, + CACHE_CONTROLLER_TTL, + CHANGELOG_HORIZON_OFFSET, + CHECK_CACHE_LIMIT, + CHECK_DISPATCH_THROTTLING_ENABLED, + CHECK_DISPATCH_THROTTLING_FREQUENCY, + CHECK_DISPATCH_THROTTLING_MAX_THRESHOLD, + CHECK_DISPATCH_THROTTLING_THRESHOLD, + CHECK_ITERATOR_CACHE_ENABLED, + CHECK_ITERATOR_CACHE_MAX_RESULTS, + CHECK_ITERATOR_CACHE_TTL, + CHECK_QUERY_CACHE_ENABLED, + CHECK_QUERY_CACHE_LIMIT, + CHECK_QUERY_CACHE_TTL, + CONTEXT_PROPAGATION_TO_DATASTORE, + DATASTORE_CONN_MAX_IDLE_TIME, + DATASTORE_CONN_MAX_LIFETIME, + DATASTORE_ENGINE, + DATASTORE_MAX_CACHE_SIZE, + DATASTORE_MAX_IDLE_CONNS, + DATASTORE_MAX_OPEN_CONNS, + DATASTORE_METRICS_ENABLED, + EXPERIMENTALS, + GRPC_ADDR, + GRPC_TLS_ENABLED, + HTTP_ADDR, + HTTP_CORS_ALLOWED_HEADERS, + HTTP_CORS_ALLOWED_ORIGINS, + HTTP_ENABLED, + HTTP_TLS_ENABLED, + HTTP_UPSTREAM_TIMEOUT, + LIST_OBJECTS_DEADLINE, + LIST_OBJECTS_DISPATCH_THROTTLING_ENABLED, + LIST_OBJECTS_DISPATCH_THROTTLING_FREQUENCY, + LIST_OBJECTS_DISPATCH_THROTTLING_MAX_THRESHOLD, + LIST_OBJECTS_DISPATCH_THROTTLING_THRESHOLD, + LIST_OBJECTS_ITERATOR_CACHE_ENABLED, + LIST_OBJECTS_ITERATOR_CACHE_MAX_RESULTS, + LIST_OBJECTS_ITERATOR_CACHE_TTL, + LIST_OBJECTS_MAX_RESULTS, + LIST_USERS_DEADLINE, + LIST_USERS_DISPATCH_THROTTLING_ENABLED, + LIST_USERS_DISPATCH_THROTTLING_FREQUENCY, + LIST_USERS_DISPATCH_THROTTLING_MAX_THRESHOLD, + LIST_USERS_DISPATCH_THROTTLING_THRESHOLD, + LIST_USERS_MAX_RESULTS, + LOG_FORMAT, + LOG_LEVEL, + LOG_TIMESTAMP_FORMAT, + MAX_AUTHORIZATION_MODEL_SIZE_IN_BYTES, + MAX_CHECKS_PER_BATCH_CHECK, + MAX_CONCURRENT_CHECKS_PER_BATCH_CHECK, + MAX_CONCURRENT_READS_FOR_CHECK, + MAX_CONCURRENT_READS_FOR_LIST_OBJECTS, + MAX_CONCURRENT_READS_FOR_LIST_USERS, + MAX_CONDITION_EVALUATION_COST, + MAX_TUPLES_PER_WRITE, + MAX_TYPES_PER_AUTHORIZATION_MODEL, + METRICS_ADDR, + METRICS_ENABLE_RPCHISTOGRAMS, + METRICS_ENABLED, + PLANNER_CLEANUP_INTERVAL, + PLANNER_EVICTION_THRESHOLD, + PLANNER_INITIAL_GUESS, + PLAYGROUND_ENABLED, + PLAYGROUND_PORT, + PROFILER_ADDR, + PROFILER_ENABLED, + REQUEST_DURATION_DATASTORE_QUERY_COUNT_BUCKETS, + REQUEST_DURATION_DISPATCH_COUNT_BUCKETS, + REQUEST_TIMEOUT, + RESOLVE_NODE_BREADTH_LIMIT, + RESOLVE_NODE_LIMIT, + SHARED_ITERATOR_ENABLED, + SHARED_ITERATOR_LIMIT, + TRACE_ENABLED, + TRACE_OTLP_ENDPOINT, + TRACE_OTLP_TLS_ENABLED, + TRACE_SAMPLE_RATIO, + TRACE_SERVICE_NAME, +} as const; + +/** + * Type representing all available product configuration constants + */ +export type ProductConfigConstants = typeof PRODUCT_CONFIG_DEFAULTS;