@stacksjs/config 0.70.380 → 0.71.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/defaults.js CHANGED
@@ -1,4 +1,4 @@
1
- var {require}=import.meta;import{commandsPath,projectPath,userDatabasePath}from"@stacksjs/path";export const FRAMEWORK_DEFAULTS={awsRegion:"us-east-1",timezone:"UTC",noReplyEmail:"no-reply@stacksjs.com",fallbackDomain:"stacks.localhost"};function deriveAppDefaults(){try{const pkgPath=projectPath("package.json"),raw=(require(pkgPath).name??"").trim();if(!raw)return{name:"Stacks",url:"stacks.localhost"};const slug=raw.replace(/^@[^/]+\//,"").toLowerCase();return{name:slug.replace(/[-_]+/g," ").replace(/(^|\s)\w/g,(c)=>c.toUpperCase()),url:`${slug}.localhost`}}catch{return{name:"Stacks",url:"stacks.localhost"}}}const appDefaults=deriveAppDefaults();export const defaults={cms:{enabled:!1},commerce:{enabled:!1},marketing:{enabled:!1},monitoring:{enabled:!1},ai:{deploy:!1,models:["anthropic.claude-sonnet-4-20250514-v1:0","anthropic.claude-haiku-4-20250514-v1:0","anthropic.claude-3-5-sonnet-20241022-v2:0","amazon.titan-embed-text-v2:0","amazon.titan-text-premier-v1:0","amazon.titan-image-generator-v2:0","meta.llama3-1-70b-instruct-v1:0","meta.llama3-1-8b-instruct-v1:0"]},auth:{username:"email",password:"password",defaultTokenName:"auth-token",cookie:{name:"auth-token"},tokenExpiry:3600000,refreshTokenExpiry:2592000000,defaultAbilities:["*"]},realtime:{driver:"pusher"},analytics:{driver:void 0},app:{name:appDefaults.name,description:"A Stacks application.",env:"local",url:appDefaults.url,debug:!0,key:"",timezone:FRAMEWORK_DEFAULTS.timezone,locale:"en",fallbackLocale:"en",cipher:"AES-256-CBC",docMode:!1,redirectUrls:[],maintenanceMode:!1,comingSoonMode:!1,comingSoonSecret:""},cli:{name:"My Custom CLI",command:"my-custom-cli",description:"Stacks is a full-stack framework for TypeScript.",source:commandsPath(),deploy:!1},cache:{driver:"memory",prefix:"stx",ttl:3600,maxKeys:-1,useClones:!0,drivers:{redis:{host:"localhost",port:6379,username:"",password:"",database:0,tls:!1},memory:{maxKeys:-1,checkPeriod:600,deleteOnExpire:!0}}},featureFlags:{default:"memory",missing:"false",drivers:{memory:{cloneValues:!0},database:{table:"feature_flags",autoCreate:!1}}},cloud:{infrastructure:{type:"serverless",driver:"aws",environments:["production","staging","development"],firewall:{enabled:!0,countryCodes:[],ipAddresses:[],queryString:[],httpHeaders:[],rateLimitPerMinute:1000,useIpReputationLists:!0,useKnownBadInputsRuleSet:!0},cdn:{allowedMethods:"GET_HEAD",cachedMethods:"GET_HEAD",minTtl:0,defaultTtl:86400,maxTtl:31536000,compress:!0,priceClass:"PriceClass_All",originShieldRegion:FRAMEWORK_DEFAULTS.awsRegion,cookieBehavior:"none",allowList:{cookies:[],headers:[],queryStrings:[]},realtimeLogs:{enabled:!0,samplingRate:2}},fileSystem:!1,storage:{}},sites:{root:"",path:""}},dashboard:{sections:{library:{enabled:!0},content:{enabled:!0},commerce:{enabled:!0},marketing:{enabled:!0},analytics:{enabled:!0},management:{enabled:!0},utilities:{enabled:!0}}},database:{default:"sqlite",logging:!1,connections:{sqlite:{database:userDatabasePath("stacks.sqlite"),prefix:""}},migrations:"migrations",migrationLocks:"migration_locks"},dns:{driver:"aws",a:[],aaaa:[],cname:[],mx:[],txt:[]},docs:{lang:"en-US",lastUpdated:!0,deploy:!1,themeConfig:{editLink:{pattern:"https://github.com/stacksjs/stacks/edit/main/docs/docs/:path",text:"Edit this page on GitHub"},footer:{message:"Released under the MIT License.",copyright:"Copyright \xA9 2024-present Stacks.js, Inc."}}},email:{from:{name:"Stacks",address:FRAMEWORK_DEFAULTS.noReplyEmail},mailboxes:[],server:{enabled:!0,scan:!0}},errors:{messages:{string:"The {{ field }} field must be a string",email:"The {{ field }} field must be a valid email address",regex:"The {{ field }} field format is invalid",url:"The {{ field }} field must be a valid URL",activeUrl:"The {{ field }} field must be a valid URL",alpha:"The {{ field }} field must contain only letters",alphaNumeric:"The {{ field }} field must contain only letters and numbers","min(":"The {{ field }} field must have at least {{ min }} characters",maxLength:"The {{ field }} field must not be greater than {{ max }} characters",fixedLength:"The {{ field }} field must be {{ size }} characters long",confirmed:"The {{ field }} field and {{ otherField }} field must be the same",endsWith:"The {{ field }} field must end with {{ substring }}",startsWith:"The {{ field }} field must start with {{ substring }}",sameAs:"The {{ field }} field and {{ otherField }} field must be the same",notSameAs:"The {{ field }} field and {{ otherField }} field must be different",in:"The selected {{ field }} is invalid",notIn:"The selected {{ field }} is invalid",ipAddress:"The {{ field }} field must be a valid IP address",uuid:"The {{ field }} field must be a valid UUID",ascii:"The {{ field }} field must only contain ASCII characters",creditCard:"The {{ field }} field must be a valid {{ providersList }} card number",hexCode:"The {{ field }} field must be a valid hex color code",iban:"The {{ field }} field must be a valid IBAN number",jwt:"The {{ field }} field must be a valid JWT token",coordinates:"The {{ field }} field must contain latitude and longitude coordinates",mobile:"The {{ field }} field must be a valid mobile phone number",passport:"The {{ field }} field must be a valid passport number",postalCode:"The {{ field }} field must be a valid postal code",boolean:"The value must be a boolean",number:"The {{ field }} field must be a number",min:"The {{ field }} field must be at least {{ min }}",max:"The {{ field }} field must not be greater than {{ max }}",range:"The {{ field }} field must be between {{ min }} and {{ max }}",positive:"The {{ field }} field must be positive",negative:"The {{ field }} field must be negative",decimal:"The {{ field }} field must have {{ digits }} decimal places",withoutDecimals:"The {{ field }} field must not have decimal places",date:"The {{ field }} field must be a datetime value","date.equals":"The {{ field }} field must be a date equal to {{ expectedValue }}","date.after":"The {{ field }} field must be a date after {{ expectedValue }}","date.before":"The {{ field }} field must be a date before {{ expectedValue }}","date.afterOrEqual":"The {{ field }} field must be a date after or equal to {{ expectedValue }}","date.beforeOrEqual":"The {{ field }} field must be a date before or equal to {{ expectedValue }}","date.sameAs":"The {{ field }} field and {{ otherField }} field must be the same","date.notSameAs":"The {{ field }} field and {{ otherField }} field must be different","date.afterField":"The {{ field }} field must be a date after {{ otherField }}",accepted:"The {{ field }} field must be accepted",enum:"The selected {{ field }} is invalid",literal:"The {{ field }} field must be {{ expectedValue }}",object:"The {{ field }} field must be an object",record:"The {{ field }} field must be an object","record.min(":"The {{ field }} field must have at least {{ min }} items","record.maxLength":"The {{ field }} field must not have more than {{ max }} items","record.fixedLength":"The {{ field }} field must contain {{ size }} items",array:"The {{ field }} field must be an array","array.min(":"The {{ field }} field must have at least {{ min }} items","array.maxLength":"The {{ field }} field must not have more than {{ max }} items","array.fixedLength":"The {{ field }} field must contain {{ size }} items",notEmpty:"The {{ field }} field must not be empty",distinct:"The {{ field }} field has duplicate values",tuple:"The {{ field }} field must be an array",union:"Invalid value provided for {{ field }} field",unionGroup:"Invalid value provided for {{ field }} field",unionOfTypes:"Invalid value provided for {{ field }} field"}},git:{hooks:{"pre-commit":"lint-staged"},scopes:["","ci","deps","dx","release","docs","test","core","actions","arrays","auth","build","cache","cli","cloud","collections","config","database","datetime","docs","errors","git","lint","modules","notifications","objects","path","realtime","router","buddy","security","server","storage","strings","tests","types","ui","utils"],messages:{type:"Select the type of change that you're committing:",scope:"Select the SCOPE of this change (optional):",customScope:"Select the SCOPE of this change:",subject:`Write a SHORT, IMPERATIVE tense description of the change:
1
+ var {require}=import.meta;import{commandsPath,projectPath,userDatabasePath}from"@stacksjs/path";export const FRAMEWORK_DEFAULTS={awsRegion:"us-east-1",timezone:"UTC",noReplyEmail:"no-reply@stacksjs.com",fallbackDomain:"stacks.localhost"};function deriveAppDefaults(){try{const pkgPath=projectPath("package.json"),raw=(require(pkgPath).name??"").trim();if(!raw)return{name:"Stacks",url:"stacks.localhost"};const slug=raw.replace(/^@[^/]+\//,"").toLowerCase();return{name:slug.replace(/[-_]+/g," ").replace(/(^|\s)\w/g,(c)=>c.toUpperCase()),url:`${slug}.localhost`}}catch{return{name:"Stacks",url:"stacks.localhost"}}}const appDefaults=deriveAppDefaults();export const defaults={cms:{enabled:!1},commerce:{enabled:!1},marketing:{enabled:!1},monitoring:{enabled:!1},sites:{enabled:!1},forms:{enabled:!1},ai:{deploy:!1,models:["anthropic.claude-sonnet-4-20250514-v1:0","anthropic.claude-haiku-4-20250514-v1:0","anthropic.claude-3-5-sonnet-20241022-v2:0","amazon.titan-embed-text-v2:0","amazon.titan-text-premier-v1:0","amazon.titan-image-generator-v2:0","meta.llama3-1-70b-instruct-v1:0","meta.llama3-1-8b-instruct-v1:0"]},auth:{username:"email",password:"password",defaultTokenName:"auth-token",cookie:{name:"auth-token"},tokenExpiry:3600000,refreshTokenExpiry:2592000000,defaultAbilities:["*"]},realtime:{driver:"pusher"},analytics:{driver:void 0},app:{name:appDefaults.name,description:"A Stacks application.",env:"local",url:appDefaults.url,debug:!0,key:"",timezone:FRAMEWORK_DEFAULTS.timezone,locale:"en",fallbackLocale:"en",cipher:"AES-256-CBC",docMode:!1,redirectUrls:[],maintenanceMode:!1,comingSoonMode:!1,comingSoonSecret:""},cli:{name:"My Custom CLI",command:"my-custom-cli",description:"Stacks is a full-stack framework for TypeScript.",source:commandsPath(),deploy:!1},cache:{driver:"memory",prefix:"stx",ttl:3600,maxKeys:-1,useClones:!0,drivers:{redis:{host:"localhost",port:6379,username:"",password:"",database:0,tls:!1},memory:{maxKeys:-1,checkPeriod:600,deleteOnExpire:!0}}},featureFlags:{default:"memory",missing:"false",drivers:{memory:{cloneValues:!0},database:{table:"feature_flags",autoCreate:!1}}},cloud:{infrastructure:{type:"serverless",driver:"aws",environments:["production","staging","development"],firewall:{enabled:!0,countryCodes:[],ipAddresses:[],queryString:[],httpHeaders:[],rateLimitPerMinute:1000,useIpReputationLists:!0,useKnownBadInputsRuleSet:!0},cdn:{allowedMethods:"GET_HEAD",cachedMethods:"GET_HEAD",minTtl:0,defaultTtl:86400,maxTtl:31536000,compress:!0,priceClass:"PriceClass_All",originShieldRegion:FRAMEWORK_DEFAULTS.awsRegion,cookieBehavior:"none",allowList:{cookies:[],headers:[],queryStrings:[]},realtimeLogs:{enabled:!0,samplingRate:2}},fileSystem:!1,storage:{}},sites:{root:"",path:""}},dashboard:{sections:{library:{enabled:!0},content:{enabled:!0},commerce:{enabled:!0},marketing:{enabled:!0},analytics:{enabled:!0},management:{enabled:!0},utilities:{enabled:!0}}},database:{default:"sqlite",logging:!1,connections:{sqlite:{database:userDatabasePath("stacks.sqlite"),prefix:""}},migrations:"migrations",migrationLocks:"migration_locks"},dns:{driver:"aws",a:[],aaaa:[],cname:[],mx:[],txt:[]},docs:{lang:"en-US",lastUpdated:!0,deploy:!1,themeConfig:{editLink:{pattern:"https://github.com/stacksjs/stacks/edit/main/docs/docs/:path",text:"Edit this page on GitHub"},footer:{message:"Released under the MIT License.",copyright:"Copyright \xA9 2024-present Stacks.js, Inc."}}},email:{from:{name:"Stacks",address:FRAMEWORK_DEFAULTS.noReplyEmail},mailboxes:[],server:{enabled:!0,scan:!0}},errors:{messages:{string:"The {{ field }} field must be a string",email:"The {{ field }} field must be a valid email address",regex:"The {{ field }} field format is invalid",url:"The {{ field }} field must be a valid URL",activeUrl:"The {{ field }} field must be a valid URL",alpha:"The {{ field }} field must contain only letters",alphaNumeric:"The {{ field }} field must contain only letters and numbers","min(":"The {{ field }} field must have at least {{ min }} characters",maxLength:"The {{ field }} field must not be greater than {{ max }} characters",fixedLength:"The {{ field }} field must be {{ size }} characters long",confirmed:"The {{ field }} field and {{ otherField }} field must be the same",endsWith:"The {{ field }} field must end with {{ substring }}",startsWith:"The {{ field }} field must start with {{ substring }}",sameAs:"The {{ field }} field and {{ otherField }} field must be the same",notSameAs:"The {{ field }} field and {{ otherField }} field must be different",in:"The selected {{ field }} is invalid",notIn:"The selected {{ field }} is invalid",ipAddress:"The {{ field }} field must be a valid IP address",uuid:"The {{ field }} field must be a valid UUID",ascii:"The {{ field }} field must only contain ASCII characters",creditCard:"The {{ field }} field must be a valid {{ providersList }} card number",hexCode:"The {{ field }} field must be a valid hex color code",iban:"The {{ field }} field must be a valid IBAN number",jwt:"The {{ field }} field must be a valid JWT token",coordinates:"The {{ field }} field must contain latitude and longitude coordinates",mobile:"The {{ field }} field must be a valid mobile phone number",passport:"The {{ field }} field must be a valid passport number",postalCode:"The {{ field }} field must be a valid postal code",boolean:"The value must be a boolean",number:"The {{ field }} field must be a number",min:"The {{ field }} field must be at least {{ min }}",max:"The {{ field }} field must not be greater than {{ max }}",range:"The {{ field }} field must be between {{ min }} and {{ max }}",positive:"The {{ field }} field must be positive",negative:"The {{ field }} field must be negative",decimal:"The {{ field }} field must have {{ digits }} decimal places",withoutDecimals:"The {{ field }} field must not have decimal places",date:"The {{ field }} field must be a datetime value","date.equals":"The {{ field }} field must be a date equal to {{ expectedValue }}","date.after":"The {{ field }} field must be a date after {{ expectedValue }}","date.before":"The {{ field }} field must be a date before {{ expectedValue }}","date.afterOrEqual":"The {{ field }} field must be a date after or equal to {{ expectedValue }}","date.beforeOrEqual":"The {{ field }} field must be a date before or equal to {{ expectedValue }}","date.sameAs":"The {{ field }} field and {{ otherField }} field must be the same","date.notSameAs":"The {{ field }} field and {{ otherField }} field must be different","date.afterField":"The {{ field }} field must be a date after {{ otherField }}",accepted:"The {{ field }} field must be accepted",enum:"The selected {{ field }} is invalid",literal:"The {{ field }} field must be {{ expectedValue }}",object:"The {{ field }} field must be an object",record:"The {{ field }} field must be an object","record.min(":"The {{ field }} field must have at least {{ min }} items","record.maxLength":"The {{ field }} field must not have more than {{ max }} items","record.fixedLength":"The {{ field }} field must contain {{ size }} items",array:"The {{ field }} field must be an array","array.min(":"The {{ field }} field must have at least {{ min }} items","array.maxLength":"The {{ field }} field must not have more than {{ max }} items","array.fixedLength":"The {{ field }} field must contain {{ size }} items",notEmpty:"The {{ field }} field must not be empty",distinct:"The {{ field }} field has duplicate values",tuple:"The {{ field }} field must be an array",union:"Invalid value provided for {{ field }} field",unionGroup:"Invalid value provided for {{ field }} field",unionOfTypes:"Invalid value provided for {{ field }} field"}},git:{hooks:{"pre-commit":"lint-staged"},scopes:["","ci","deps","dx","release","docs","test","core","actions","arrays","auth","build","cache","cli","cloud","collections","config","database","datetime","docs","errors","git","lint","modules","notifications","objects","path","realtime","router","buddy","security","server","storage","strings","tests","types","ui","utils"],messages:{type:"Select the type of change that you're committing:",scope:"Select the SCOPE of this change (optional):",customScope:"Select the SCOPE of this change:",subject:`Write a SHORT, IMPERATIVE tense description of the change:
2
2
  `,body:`Provide a LONGER description of the change (optional). Use "|" to break new line:
3
3
  `,breaking:`List any BREAKING CHANGES (optional). Use "|" to break new line:
4
4
  `,footerPrefixesSelect:"Select the ISSUES type of the change list by this change (optional):",customFooterPrefixes:"Input ISSUES prefix:",footer:`List any ISSUES by this change. E.g.: #31, #34:
@@ -35,5 +35,5 @@ export declare function resetFeature(name: string): void;
35
35
  * framework features plus any runtime overrides for ad-hoc flags.
36
36
  */
37
37
  export declare function listFeatures(): Record<string, boolean>;
38
- export type StacksFeature = | 'auth' | 'marketing' | 'cms' | 'commerce'
38
+ export type StacksFeature = | 'auth' | 'marketing' | 'cms' | 'commerce' | 'forms'
39
39
  | 'dashboard' | 'monitoring' | 'realtime' | 'queue';
package/dist/features.js CHANGED
@@ -1 +1 @@
1
- import{config}from"./config";const FEATURE_NAMES=["auth","marketing","cms","commerce","dashboard","monitoring","realtime","queue"],FEATURE_DEFAULTS={dashboard:!0},overrides=new Map;function configFor(name){const raw=config[name];return raw&&typeof raw==="object"?raw:void 0}export function feature(name){if(overrides.has(name))return overrides.get(name);const cfg=configFor(name);if(cfg){const enabledField=cfg.enabled;if(enabledField===!1)return!1;if(Array.isArray(cfg.env)&&cfg.env.length>0){const currentEnv=(config.app?.env??"").toString();if(!cfg.env.includes(currentEnv))return!1}if(enabledField!==void 0)return!!enabledField;return!0}return FEATURE_DEFAULTS[name]??!1}export function enableFeature(name){overrides.set(name,!0)}export function disableFeature(name){overrides.set(name,!1)}export function resetFeature(name){overrides.delete(name)}export function listFeatures(){const out={};for(const name of FEATURE_NAMES)out[name]=feature(name);for(const name of overrides.keys())out[name]=feature(name);return out}
1
+ import{config}from"./config";const FEATURE_NAMES=["auth","marketing","cms","commerce","forms","dashboard","monitoring","realtime","queue"],FEATURE_DEFAULTS={dashboard:!0},overrides=new Map;function configFor(name){const raw=config[name];return raw&&typeof raw==="object"?raw:void 0}export function feature(name){if(overrides.has(name))return overrides.get(name);const cfg=configFor(name);if(cfg){const enabledField=cfg.enabled;if(enabledField===!1)return!1;if(Array.isArray(cfg.env)&&cfg.env.length>0){const currentEnv=(config.app?.env??"").toString();if(!cfg.env.includes(currentEnv))return!1}if(enabledField!==void 0)return!!enabledField;return!0}return FEATURE_DEFAULTS[name]??!1}export function enableFeature(name){overrides.set(name,!0)}export function disableFeature(name){overrides.set(name,!1)}export function resetFeature(name){overrides.delete(name)}export function listFeatures(){const out={};for(const name of FEATURE_NAMES)out[name]=feature(name);for(const name of overrides.keys())out[name]=feature(name);return out}
package/dist/overrides.js CHANGED
@@ -1,4 +1,4 @@
1
- import{resolve}from"node:path";import{pathToFileURL}from"node:url";import{defaults}from"./defaults";import{validateConfig}from"./validators";const skipConfigLoading=process.env.SKIP_CONFIG_LOADING==="true",skipConfigValidation=process.env.SKIP_CONFIG_VALIDATION==="true",OVERRIDES_KEY=Symbol.for("@stacksjs/config:overrides"),READY_KEY=Symbol.for("@stacksjs/config:overridesReady");function defaultsForOverrides(){return{ai:{},analytics:{},app:{...defaults.app,name:process.env.APP_NAME||defaults.app?.name||"Stacks",env:process.env.APP_ENV||"production"},auth:{},cache:{},cli:{},cloud:{},cms:{},commerce:{},dashboard:{},database:{},dns:{},realtime:{},email:{},errors:{},featureFlags:{},git:{},hashing:{},images:{},library:{},logging:{},marketing:{},monitoring:{},notification:{},queue:{},payment:{},ports:{},saas:{},searchEngine:{},security:{},server:{},services:{},filesystems:{},team:{},ui:{}}}const globalScope=globalThis,sharedOverrides=globalScope[OVERRIDES_KEY];export const overrides=sharedOverrides??(()=>{const created=defaultsForOverrides();globalScope[OVERRIDES_KEY]=created;return created})();const userConfigs=[["ai","ai"],["analytics","analytics"],["app","app"],["auth","auth"],["cache","cache"],["cli","cli"],["cloud","cloud"],["cms","cms"],["commerce","commerce"],["dashboard","dashboard"],["database","database"],["dns","dns"],["docs","docs"],["email","email"],["errors","errors"],["featureFlags","feature-flags"],["git","git"],["hashing","hashing"],["images","images"],["library","library"],["logging","logging"],["marketing","marketing"],["monitoring","monitoring"],["notification","notification"],["payment","payment"],["ports","ports"],["queue","queue"],["realtime","realtime"],["saas","saas"],["searchEngine","search-engine"],["security","security"],["server","server"],["services","services"],["filesystems","filesystems"],["team","team"],["ui","ui"]];export function userConfigUrl(name,cwd=process.cwd()){return pathToFileURL(resolve(cwd,"config",`${name}.ts`)).href}const sharedReady=globalScope[READY_KEY];export const overridesReady=sharedReady??(()=>{const promise=skipConfigLoading?Promise.resolve(overrides):Promise.all(userConfigs.map(async([key,name])=>{const modulePath=userConfigUrl(name);try{const mod=await import(modulePath);if(mod?.default!==void 0)overrides[key]=mod.default}catch(err){const code=err?.code,msg=err?.message??String(err);if(!(code==="ERR_MODULE_NOT_FOUND"||code==="MODULE_NOT_FOUND"||/Cannot find module/i.test(msg)))console.warn(`[config] Failed to load ${String(key)} config from ${modulePath}: ${msg}`)}})).then(()=>{if(!skipConfigValidation){const issues=validateConfig(overrides);if(issues.length>0){console.error("[config] Configuration issues detected:");for(const issue of issues)console.error(` \u2022 ${issue.path}: ${issue.message}`);const summary=issues.map((i)=>` \u2022 ${i.path}: ${i.message}`).join(`
1
+ import{resolve}from"node:path";import{pathToFileURL}from"node:url";import{defaults}from"./defaults";import{validateConfig}from"./validators";const skipConfigLoading=process.env.SKIP_CONFIG_LOADING==="true",skipConfigValidation=process.env.SKIP_CONFIG_VALIDATION==="true",OVERRIDES_KEY=Symbol.for("@stacksjs/config:overrides"),READY_KEY=Symbol.for("@stacksjs/config:overridesReady");function defaultsForOverrides(){return{ai:{},analytics:{},app:{...defaults.app,name:process.env.APP_NAME||defaults.app?.name||"Stacks",env:process.env.APP_ENV||"production"},auth:{},cache:{},cli:{},cloud:{},cms:{},commerce:{},dashboard:{},database:{},dns:{},realtime:{},email:{},errors:{},featureFlags:{},git:{},hashing:{},images:{},library:{},logging:{},marketing:{},monitoring:{},notification:{},queue:{},payment:{},ports:{},saas:{},searchEngine:{},security:{},server:{},sites:{},forms:{},services:{},filesystems:{},team:{},ui:{}}}const globalScope=globalThis,sharedOverrides=globalScope[OVERRIDES_KEY];export const overrides=sharedOverrides??(()=>{const created=defaultsForOverrides();globalScope[OVERRIDES_KEY]=created;return created})();const userConfigs=[["ai","ai"],["analytics","analytics"],["app","app"],["auth","auth"],["cache","cache"],["cli","cli"],["cloud","cloud"],["cms","cms"],["commerce","commerce"],["dashboard","dashboard"],["database","database"],["dns","dns"],["docs","docs"],["email","email"],["errors","errors"],["featureFlags","feature-flags"],["git","git"],["hashing","hashing"],["images","images"],["library","library"],["logging","logging"],["marketing","marketing"],["monitoring","monitoring"],["notification","notification"],["payment","payment"],["ports","ports"],["queue","queue"],["realtime","realtime"],["saas","saas"],["searchEngine","search-engine"],["security","security"],["sites","sites"],["forms","forms"],["server","server"],["services","services"],["filesystems","filesystems"],["team","team"],["ui","ui"]];export function userConfigUrl(name,cwd=process.cwd()){return pathToFileURL(resolve(cwd,"config",`${name}.ts`)).href}const sharedReady=globalScope[READY_KEY];export const overridesReady=sharedReady??(()=>{const promise=skipConfigLoading?Promise.resolve(overrides):Promise.all(userConfigs.map(async([key,name])=>{const modulePath=userConfigUrl(name);try{const mod=await import(modulePath);if(mod?.default!==void 0)overrides[key]=mod.default}catch(err){const code=err?.code,msg=err?.message??String(err);if(!(code==="ERR_MODULE_NOT_FOUND"||code==="MODULE_NOT_FOUND"||/Cannot find module/i.test(msg)))console.warn(`[config] Failed to load ${String(key)} config from ${modulePath}: ${msg}`)}})).then(()=>{if(!skipConfigValidation){const issues=validateConfig(overrides);if(issues.length>0){console.error("[config] Configuration issues detected:");for(const issue of issues)console.error(` \u2022 ${issue.path}: ${issue.message}`);const summary=issues.map((i)=>` \u2022 ${i.path}: ${i.message}`).join(`
2
2
  `);throw Error(`[config] ${issues.length} configuration issue(s) detected at boot:
3
3
  ${summary}
4
4
  Set SKIP_CONFIG_VALIDATION=true to bypass (e.g. when running migrations against partial config).`)}}return overrides});globalScope[READY_KEY]=promise;return promise})();export default overrides;
@@ -38,6 +38,7 @@ export declare function useRequestEvent(): {
38
38
  locale: string
39
39
  ip: string
40
40
  host: string
41
+ site: SiteSnapshot | null
41
42
  };
42
43
  /**
43
44
  * One request object for `<script server>` blocks (stacksjs/stacks#2232).
@@ -84,6 +85,23 @@ export declare interface RequestContextSnapshot {
84
85
  params?: Record<string, string>
85
86
  ip?: string
86
87
  host?: string
88
+ site?: SiteSnapshot | null
89
+ }
90
+ /**
91
+ * The site a multi-site server resolved for this request's Host header.
92
+ *
93
+ * Carried on the snapshot rather than AsyncLocalStorage because ALS does not
94
+ * survive into stx-serve's render (see the module comment): a `<script server>`
95
+ * block that asked an ALS-backed `currentSite()` would silently get undefined.
96
+ * The resolving server (`@stacksjs/sites` middleware / onRequest hook) stashes
97
+ * it here; pages read `requestContext.site()`.
98
+ */
99
+ export declare interface SiteSnapshot {
100
+ id: number
101
+ uuid?: string
102
+ name?: string
103
+ subdomain?: string
104
+ settings?: Record<string, unknown>
87
105
  }
88
106
  /** What a `<script server>` block sees as `requestContext`. */
89
107
  export declare interface StacksRequestContext {
@@ -97,4 +115,5 @@ export declare interface StacksRequestContext {
97
115
  locale: () => string
98
116
  ip: () => string
99
117
  host: () => string
118
+ site: () => SiteSnapshot | null
100
119
  }
@@ -1 +1 @@
1
- export function parseCookieHeader(header){const out={};if(!header)return out;for(const part of header.split(";")){const trimmed=part.trim(),eq=trimmed.indexOf("=");if(eq===-1)continue;const key=trimmed.slice(0,eq).trim();if(!key)continue;const value=trimmed.slice(eq+1).trim();try{out[key]=decodeURIComponent(value)}catch{out[key]=value}}return out}export function createRequestContext(read){const snapshot=()=>read()??{},searchOf=()=>{const direct=snapshot().search;if(direct)return direct;const url=snapshot().url??"",mark=url.indexOf("?");return mark===-1?"":url.slice(mark)};return{cookie:(name)=>snapshot().cookies?.[name]??null,cookies:()=>snapshot().cookies??{},url:()=>snapshot().url??"",path:()=>{const direct=snapshot().path;if(direct)return direct;const url=snapshot().url??"";if(!url)return"";try{return new URL(url).pathname}catch{const mark=url.indexOf("?");return mark===-1?url:url.slice(0,mark)}},search:searchOf,query:()=>{const out={},search=searchOf();if(!search)return out;new URLSearchParams(search.startsWith("?")?search.slice(1):search).forEach((value,key)=>{out[key]=value});return out},params:()=>snapshot().params??{},locale:()=>snapshot().locale??"en",ip:()=>snapshot().ip??"",host:()=>snapshot().host??""}}export function installRequestContext(read){const context=createRequestContext(read);globalThis.requestContext=context;return context}export function useRequestEvent(){const context=globalThis.requestContext??createRequestContext(()=>{return});return{url:context.url(),path:context.path(),search:context.search(),query:context.query(),cookies:context.cookies(),params:context.params(),locale:context.locale(),ip:context.ip(),host:context.host()}}
1
+ export function parseCookieHeader(header){const out={};if(!header)return out;for(const part of header.split(";")){const trimmed=part.trim(),eq=trimmed.indexOf("=");if(eq===-1)continue;const key=trimmed.slice(0,eq).trim();if(!key)continue;const value=trimmed.slice(eq+1).trim();try{out[key]=decodeURIComponent(value)}catch{out[key]=value}}return out}export function createRequestContext(read){const snapshot=()=>read()??{},searchOf=()=>{const direct=snapshot().search;if(direct)return direct;const url=snapshot().url??"",mark=url.indexOf("?");return mark===-1?"":url.slice(mark)};return{cookie:(name)=>snapshot().cookies?.[name]??null,cookies:()=>snapshot().cookies??{},url:()=>snapshot().url??"",path:()=>{const direct=snapshot().path;if(direct)return direct;const url=snapshot().url??"";if(!url)return"";try{return new URL(url).pathname}catch{const mark=url.indexOf("?");return mark===-1?url:url.slice(0,mark)}},search:searchOf,query:()=>{const out={},search=searchOf();if(!search)return out;new URLSearchParams(search.startsWith("?")?search.slice(1):search).forEach((value,key)=>{out[key]=value});return out},params:()=>snapshot().params??{},locale:()=>snapshot().locale??"en",ip:()=>snapshot().ip??"",host:()=>snapshot().host??"",site:()=>snapshot().site??null}}export function installRequestContext(read){const context=createRequestContext(read);globalThis.requestContext=context;return context}export function useRequestEvent(){const context=globalThis.requestContext??createRequestContext(()=>{return});return{url:context.url(),path:context.path(),search:context.search(),query:context.query(),cookies:context.cookies(),params:context.params(),locale:context.locale(),ip:context.ip(),host:context.host(),site:context.site()}}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/config",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.70.380",
5
+ "version": "0.71.2",
6
6
  "description": "The Stacks config helper methods.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -55,11 +55,11 @@
55
55
  "prepublishOnly": "bun run build"
56
56
  },
57
57
  "dependencies": {
58
- "ts-pantry": "^0.11.0"
58
+ "ts-pantry": "^0.11.27"
59
59
  },
60
60
  "devDependencies": {
61
- "@stacksjs/alias": "0.70.380",
62
- "better-dx": "^0.2.17",
63
- "@stacksjs/types": "0.70.380"
61
+ "@stacksjs/alias": "0.71.2",
62
+ "better-dx": "^0.2.23",
63
+ "@stacksjs/types": "0.71.2"
64
64
  }
65
65
  }