@stacksjs/config 0.74.20 → 0.74.21

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.
@@ -0,0 +1,34 @@
1
+ /** View directories each discovered package contributes. */
2
+ export declare function packageViewRoots(options?: PackageResourceOptions): PackageResourceRoot[];
3
+ /**
4
+ * Model directories each discovered package contributes.
5
+ *
6
+ * One reader rather than one per consumer. The migration side and the
7
+ * auto-import barrel both need this answer, and they are in different packages;
8
+ * two copies of the resolution rule would eventually disagree about where a
9
+ * package lives, and routes and models would then point at different trees.
10
+ */
11
+ export declare function packageModelRoots(options?: PackageResourceOptions): PackageResourceRoot[];
12
+ /**
13
+ * The view directories that discovered packages contribute.
14
+ *
15
+ * A package declaring a `stacks` key already has its route files registered by
16
+ * the router. This is the same idea for templates, so a package can ship the
17
+ * pages that its routes render rather than asking the application to copy them
18
+ * in.
19
+ *
20
+ * The manifest is READ, not imported. `discoverPackages()` lives in
21
+ * `@stacksjs/actions`, which depends on this package, so importing it here
22
+ * would close a cycle. The router and the model resolver both read the same
23
+ * file for the same reason.
24
+ */
25
+ /** One directory a discovered package contributes. */
26
+ export declare interface PackageResourceRoot {
27
+ package: string
28
+ dir: string
29
+ }
30
+ export declare interface PackageResourceOptions {
31
+ manifestPath?: string
32
+ projectRoot?: string
33
+ exists?: (candidate: string) => boolean
34
+ }
@@ -0,0 +1 @@
1
+ import{existsSync,readFileSync}from"node:fs";import{isAbsolute,join}from"node:path";import{path}from"@stacksjs/path";const IMPLIED_DIRS={views:["resources/views"],models:["app/Models"]};function readManifest(manifestPath){try{return JSON.parse(readFileSync(manifestPath,"utf8"))?.packages??{}}catch{return{}}}function resourceRoots(field,options={}){const manifestPath=options.manifestPath??path.storagePath("framework/discovered-packages.json"),projectRoot=options.projectRoot??path.projectPath(),exists=options.exists??existsSync,roots=[];for(const[name,meta]of Object.entries(readManifest(manifestPath))){const declared=meta?.[field]??IMPLIED_DIRS[field];if(!declared)continue;const root=meta.root;if(!root||typeof root!=="string")continue;const base=isAbsolute(root)?root:join(projectRoot,root);for(const entry of Array.isArray(declared)?declared:[declared]){if(typeof entry!=="string"||!entry)continue;const cleaned=entry.replace(/^[/\\]+/,"");if(!cleaned||cleaned.split(/[/\\]/).includes(".."))continue;const dir=join(base,cleaned);if(exists(dir))roots.push({package:name,dir})}}return roots.sort((a,b)=>a.package.localeCompare(b.package))}export function packageViewRoots(options={}){return resourceRoots("views",options)}export function packageModelRoots(options={}){return resourceRoots("models",options)}
package/dist/helpers.js CHANGED
@@ -1 +1 @@
1
- import{config}from".";export async function localUrl(options={}){const domain=options.domain??config.app.url??"stacks",type=options.type??"frontend",localhost=options.localhost??!1,https=options.https,network=options.network;let url=domain.replace(/\.[^.]+$/,".localhost");async function tunnel(port){const{createLocalTunnel}=await import("@stacksjs/tunnel");return createLocalTunnel(port)}switch(type){case"frontend":if(network)return await tunnel(config.ports?.frontend||3000);if(localhost)return`http://localhost:${config.ports?.frontend}`;break;case"backend":if(network)return await tunnel(config.ports?.backend||3001);if(localhost)return`http://localhost:${config.ports?.backend}`;url=`api.${url}`;break;case"admin":if(network)return await tunnel(config.ports?.admin||3002);if(localhost)return`http://localhost:${config.ports?.admin}`;url=`admin.${url}`;break;case"library":if(network)return await tunnel(config.ports?.library||3003);if(localhost)return`http://localhost:${config.ports?.library}`;url=`libs.${url}`;break;case"email":if(network)return await tunnel(config.ports?.email||3005);if(localhost)return`http://localhost:${config.ports?.email}`;url=`email.${url}`;break;case"desktop":if(network)return await tunnel(config.ports?.desktop||3004);if(localhost)return`http://localhost:${config.ports?.desktop}`;url=`desktop.${url}`;break;case"docs":if(network)return await tunnel(config.ports?.docs||3006);if(localhost)return`http://localhost:${config.ports?.docs}`;url=`docs.${url}`;break;case"inspect":if(network)return await tunnel(config.ports?.inspect||3007);if(localhost)return`http://localhost:${config.ports?.inspect}`;url=`inspect.${url}`;break;default:if(localhost)return`http://localhost:${config.ports?.frontend}`}if(https)return`https://${url}`;return`http://${url}`}export function defineStacksConfig(config){return config}export function defineApp(config){return config}export function defineCache(config){return config}export function defineCdn(config){return config}export function defineChat(config){return config}export function defineCli(config){return config}export function defineDatabase(config){return config}export function defineDependencies(config){return config}export function defineDns(config){return config}export function defineEmailConfig(config){return config}export function defineEmail(config){return config}export function defineGit(config){return config}export function defineHashing(config){return config}export function defineImages(config){return config}export function defineLibrary(config){return config}export function defineNotification(config){return config}export function definePayment(config){return config}export function defineQueue(config){return config}export function defineSearchEngine(config){return config}export function defineSecurity(config){return config}export function defineServices(config){return config}export function defineSms(config){return config}export function defineStorage(config){return config}export function defineFilesystems(config){return config}export function defineFeatureFlags(config){return config}export function defineUi(config){return config}export{defineEvents}from"@stacksjs/events";
1
+ import{config}from".";export async function localUrl(options={}){const domain=options.domain??config.app.url??"stacks",type=options.type??"frontend",localhost=options.localhost??!1,{https,network}=options;let url=domain.replace(/\.[^.]+$/,".localhost");async function tunnel(port){const{createLocalTunnel}=await import("@stacksjs/tunnel");return createLocalTunnel(port)}switch(type){case"frontend":if(network)return await tunnel(config.ports?.frontend||3000);if(localhost)return`http://localhost:${config.ports?.frontend}`;break;case"backend":if(network)return await tunnel(config.ports?.backend||3001);if(localhost)return`http://localhost:${config.ports?.backend}`;url=`api.${url}`;break;case"admin":if(network)return await tunnel(config.ports?.admin||3002);if(localhost)return`http://localhost:${config.ports?.admin}`;url=`admin.${url}`;break;case"library":if(network)return await tunnel(config.ports?.library||3003);if(localhost)return`http://localhost:${config.ports?.library}`;url=`libs.${url}`;break;case"email":if(network)return await tunnel(config.ports?.email||3005);if(localhost)return`http://localhost:${config.ports?.email}`;url=`email.${url}`;break;case"desktop":if(network)return await tunnel(config.ports?.desktop||3004);if(localhost)return`http://localhost:${config.ports?.desktop}`;url=`desktop.${url}`;break;case"docs":if(network)return await tunnel(config.ports?.docs||3006);if(localhost)return`http://localhost:${config.ports?.docs}`;url=`docs.${url}`;break;case"inspect":if(network)return await tunnel(config.ports?.inspect||3007);if(localhost)return`http://localhost:${config.ports?.inspect}`;url=`inspect.${url}`;break;default:if(localhost)return`http://localhost:${config.ports?.frontend}`}if(https)return`https://${url}`;return`http://${url}`}export function defineStacksConfig(config){return config}export function defineApp(config){return config}export function defineCache(config){return config}export function defineCdn(config){return config}export function defineChat(config){return config}export function defineCli(config){return config}export function defineDatabase(config){return config}export function defineDependencies(config){return config}export function defineDns(config){return config}export function defineEmailConfig(config){return config}export function defineEmail(config){return config}export function defineGit(config){return config}export function defineHashing(config){return config}export function defineImages(config){return config}export function defineLibrary(config){return config}export function defineNotification(config){return config}export function definePayment(config){return config}export function defineQueue(config){return config}export function defineSearchEngine(config){return config}export function defineSecurity(config){return config}export function defineServices(config){return config}export function defineSms(config){return config}export function defineStorage(config){return config}export function defineFilesystems(config){return config}export function defineFeatureFlags(config){return config}export function defineUi(config){return config}export{defineEvents}from"@stacksjs/events";
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ export * from './config';
12
12
  export { FRAMEWORK_DEFAULTS } from './defaults';
13
13
  export { validateConfig, reportConfigIssues, type ConfigValidationIssue } from './validators';
14
14
  export { feature, enableFeature, disableFeature, resetFeature, listFeatures } from './features';
15
+ export { packageModelRoots, packageViewRoots, type PackageResourceOptions, type PackageResourceRoot } from './discovered-resources';
15
16
  export { resolveViewPatterns, type DefaultViewsSetting, type ViewPatternResolution } from './views';
16
17
  export {
17
18
  createRequestContext,
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export*from"./config";export{FRAMEWORK_DEFAULTS}from"./defaults";export{validateConfig,reportConfigIssues}from"./validators";export{feature,enableFeature,disableFeature,resetFeature,listFeatures}from"./features";export{resolveViewPatterns}from"./views";export{createRequestContext,installRequestContext,parseCookieHeader,useRequestEvent}from"./request-context";export*from"./capabilities";
1
+ export*from"./config";export{FRAMEWORK_DEFAULTS}from"./defaults";export{validateConfig,reportConfigIssues}from"./validators";export{feature,enableFeature,disableFeature,resetFeature,listFeatures}from"./features";export{packageModelRoots,packageViewRoots}from"./discovered-resources";export{resolveViewPatterns}from"./views";export{createRequestContext,installRequestContext,parseCookieHeader,useRequestEvent}from"./request-context";export*from"./capabilities";
package/dist/views.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { PackageResourceRoot } from './discovered-resources';
1
2
  /**
2
3
  * Compose the view patterns for the dev and production servers
3
4
  * (stacksjs/stacks#2237).
@@ -17,8 +18,18 @@
17
18
  *
18
19
  * `exists` is injectable so the resolution is testable without a fixture tree;
19
20
  * it defaults to the real filesystem.
21
+ *
22
+ * Views a discovered package ships are appended LAST, after everything above.
23
+ * stx's `getRoute()` returns the first pattern whose relative path matches, so
24
+ * anything appended after the existing roots cannot change the answer for a
25
+ * path that already resolves. That is what makes this additive for an app with
26
+ * no packages, and for every pre-existing route in an app with them.
27
+ *
28
+ * `defaultViews` is not consulted for packages. That setting decides whether
29
+ * the app serves the FRAMEWORK's demo views; an application that installed a
30
+ * package asked for that package's pages either way.
20
31
  */
21
- export declare function resolveViewPatterns(userViewsPath: string, defaultViewsPath: string, setting: DefaultViewsSetting | undefined, exists?: (path: string) => boolean): ViewPatternResolution;
32
+ export declare function resolveViewPatterns(userViewsPath: string, defaultViewsPath: string, setting: DefaultViewsSetting | undefined, exists?: (path: string) => boolean, packageViews?: PackageResourceRoot[]): ViewPatternResolution;
22
33
  export declare interface ViewPatternResolution {
23
34
  patterns: string[]
24
35
  missing: string[]
package/dist/views.js CHANGED
@@ -1 +1 @@
1
- import{existsSync}from"node:fs";import{join}from"node:path";export function resolveViewPatterns(userViewsPath,defaultViewsPath,setting,exists=existsSync){if(setting===void 0||setting===!0)return{patterns:[userViewsPath,defaultViewsPath],missing:[]};if(setting===!1)return{patterns:[userViewsPath],missing:[]};if(!Array.isArray(setting))return{patterns:[userViewsPath,defaultViewsPath],missing:[]};const patterns=[userViewsPath],missing=[];for(const name of setting){const cleaned=String(name).replace(/^[/\\]+/,"");if(!cleaned||cleaned.split(/[/\\]/).includes(".."))continue;const candidate=join(defaultViewsPath,cleaned);if(exists(candidate))patterns.push(candidate);else missing.push(cleaned)}return{patterns,missing}}
1
+ import{existsSync}from"node:fs";import{join}from"node:path";import{packageViewRoots}from"./discovered-resources";export function resolveViewPatterns(userViewsPath,defaultViewsPath,setting,exists=existsSync,packageViews=packageViewRoots({exists})){const fromPackages=packageViews.map((root)=>root.dir);if(setting===void 0||setting===!0)return{patterns:[userViewsPath,defaultViewsPath,...fromPackages],missing:[]};if(setting===!1)return{patterns:[userViewsPath,...fromPackages],missing:[]};if(!Array.isArray(setting))return{patterns:[userViewsPath,defaultViewsPath,...fromPackages],missing:[]};const patterns=[userViewsPath],missing=[];for(const name of setting){const cleaned=String(name).replace(/^[/\\]+/,"");if(!cleaned||cleaned.split(/[/\\]/).includes(".."))continue;const candidate=join(defaultViewsPath,cleaned);if(exists(candidate))patterns.push(candidate);else missing.push(cleaned)}patterns.push(...fromPackages);return{patterns,missing}}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/config",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.74.20",
5
+ "version": "0.74.21",
6
6
  "description": "The Stacks config helper methods.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [
@@ -55,14 +55,14 @@
55
55
  "prepublishOnly": "bun run build"
56
56
  },
57
57
  "dependencies": {
58
- "@stacksjs/events": "0.74.20",
59
- "@stacksjs/path": "0.74.20",
60
- "@stacksjs/tunnel": "0.74.20",
58
+ "@stacksjs/events": "0.74.21",
59
+ "@stacksjs/path": "0.74.21",
60
+ "@stacksjs/tunnel": "0.74.21",
61
61
  "ts-pantry": "^0.11.35"
62
62
  },
63
63
  "devDependencies": {
64
- "@stacksjs/alias": "0.74.20",
65
- "@stacksjs/types": "0.74.20",
64
+ "@stacksjs/alias": "0.74.21",
65
+ "@stacksjs/types": "0.74.21",
66
66
  "better-dx": "^0.2.24"
67
67
  }
68
68
  }