@stacksjs/server 0.75.262 → 0.75.263
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/imports.d.ts +9 -0
- package/dist/imports.js +3 -1
- package/package.json +12 -12
package/dist/imports.d.ts
CHANGED
|
@@ -70,6 +70,15 @@ export declare function autoImportSourceDirs(): string[];
|
|
|
70
70
|
* is a no-op and the loop cannot start.
|
|
71
71
|
*/
|
|
72
72
|
export declare function autoImportsAreStale(): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* The set of files the barrels are generated from, as one hash.
|
|
75
|
+
*
|
|
76
|
+
* Project-relative paths, sorted, plus the discovered package set, so it is
|
|
77
|
+
* identical on every machine holding the same tree. Paths and not contents:
|
|
78
|
+
* the registries map names to files, so a file added, removed or renamed is
|
|
79
|
+
* what makes them wrong.
|
|
80
|
+
*/
|
|
81
|
+
export declare function autoImportSourceFingerprint(): string;
|
|
73
82
|
export declare function generateAutoImportFiles(options?: GenerateAutoImportOptions): Promise<void>;
|
|
74
83
|
/**
|
|
75
84
|
* Every name a generated barrel exports, and whether it is a type alone.
|
package/dist/imports.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
var {require}=import.meta;import{existsSync,readFileSync,renameSync,statSync,unlinkSync}from"node:fs";import{dirname,isAbsolute,relative,resolve as resolvePath}from"node:path";import{fileURLToPath}from"node:url";import{plugin}from"bun";import{log}from"@stacksjs/logging/runtime";import{path}from"@stacksjs/path";import{autoImports,generateRuntimeIndex,generateGlobalsScript}from"bun-plugin-auto-imports";import{globSync}from"@stacksjs/storage/glob";import{primitiveAutoImportEntries,primitiveModules}from"./primitive-imports";import{defaultImportSpecifier,isFrameworkSourceCheckout}from"./default-import-specifier";const OPTIONAL_MODEL_MODULES={commerce:["config/commerce.ts"],Content:["config/cms.ts","config/blog.ts"],Forms:["config/forms.ts"],realtime:["config/realtime.ts"]};function configEnabled(configRelPaths){if(process.env.STACKS_CANONICAL_FEATURES==="1")return!0;return configRelPaths.some((rel)=>existsSync(path.projectPath(rel)))}export function frameworkDefaultsDir(sub){const vendored=path.storagePath(`framework/defaults/${sub}`);return resolveDefaultsDir(existsSync(vendored)?vendored:void 0,packagedDefaultsDir(sub),vendoredDefaultsAreStale())}export function resolveDefaultsDir(vendored,packaged,vendoredIsStale){if(packaged&&vendoredIsStale)return packaged;return vendored??packaged}function packagedDefaultsDir(sub){try{const packaged=`${dirname(fileURLToPath(import.meta.resolve("@stacksjs/defaults/package.json")))}/${sub}`;return existsSync(packaged)?packaged:void 0}catch{return}}function defaultsModuleSpecifier(){const roots=existingDirs([path.storagePath("framework/defaults"),packagedDefaultsDir("")]),sourceCheckout=isFrameworkSourceCheckout(path.projectPath());return(file)=>defaultImportSpecifier(file,roots,sourceCheckout)}function declarationModuleSpecifier(file,outputPath,mapper=defaultsModuleSpecifier()){if(!isAbsolute(file)&&!file.startsWith("."))return file;const canonical=mapper(file,outputPath);if(canonical)return canonical;const local=relative(dirname(outputPath),file).replace(/\\/g,"/").replace(/\.ts$/,"");return local.startsWith(".")?local:`./${local}`}let defaultsAreStale;function vendoredDefaultsAreStale(){if(defaultsAreStale===void 0)defaultsAreStale=path.inspectDefaultsProvenance().status==="stale";return defaultsAreStale}function existingDirs(dirs){return dirs.filter((dir)=>Boolean(dir)&&existsSync(dir))}function packageModelDirs(){try{const{packageModelRoots}=require("@stacksjs/config");return packageModelRoots().map((root)=>root.dir)}catch{return[]}}async function writeGeneratedFile(outputPath,contents){const temp=`${outputPath}.${process.pid}.tmp`;try{await Bun.write(temp,contents);renameSync(temp,outputPath)}catch(error){try{unlinkSync(temp)}catch{}throw error}}function packageJobDirs(){try{const{packageJobRoots}=require("@stacksjs/config");return packageJobRoots().map((root)=>root.dir)}catch{return[]}}function resolveDefaultModelDirs(){const root=frameworkDefaultsDir("app/Models");if(!root)return[];const dirs=[root];for(const[subdir,configPaths]of Object.entries(OPTIONAL_MODEL_MODULES))if(configEnabled(configPaths))dirs.push(`${root}/${subdir}`);return dirs}function scanDirTopLevel(dir){try{return globSync(`${dir}/*.ts`,{ignore:["**/*.d.ts","**/index.ts","**/README*"]}).sort()}catch{return[]}}function scanDefineModelExports(dir,opts={}){const{recursive=!0}=opts;let files=[];try{const pattern=recursive?`${dir}/**/*.ts`:`${dir}/*.ts`;files=globSync(pattern,{ignore:["**/*.d.ts","**/index.ts","**/README*"]}).sort()}catch{return[]}const exports=[],seen=new Set;for(const file of files){const basename=file.split("/").pop()?.replace(".ts","")||"";if(basename&&!seen.has(basename)){seen.add(basename);exports.push({name:basename,file,isDefault:!0})}}return exports}const GLOBAL_SHADOW_BLOCKLIST=new Set(["Error","Request","Response","URL","Map","Set","Object","Array","Number","String","Date","Promise","Symbol"]);async function generateDefineModelIndex(entries,outputPath){const lines=["// Generated by bun-plugin-auto-imports"],seen=new Set,moduleSpecifier=defaultsModuleSpecifier();for(const entry of entries){const dir=typeof entry==="string"?entry:entry.dir,recursive=typeof entry==="string"?!0:entry.recursive;let files=[];try{const pattern=recursive?`${dir}/**/*.ts`:`${dir}/*.ts`;files=globSync(pattern,{ignore:["**/*.d.ts","**/index.ts","**/README*"]}).sort()}catch{continue}for(const file of files){const basename=file.split("/").pop()?.replace(".ts","")||"";if(!basename||seen.has(basename))continue;seen.add(basename);const relativePath=moduleSpecifier(file,outputPath)??relative(dirname(outputPath),file).replace(/\\/g,"/").replace(/\.ts$/,"");if(GLOBAL_SHADOW_BLOCKLIST.has(basename)){lines.push(`// Skipped '${basename}' - would shadow a built-in global. Import directly if needed.`);lines.push(`// export { default as ${basename} } from '${relativePath}'`);continue}lines.push(`export { default as ${basename} } from '${relativePath}'`)}}await writeGeneratedFile(outputPath,`${lines.join(`
|
|
2
2
|
`)}
|
|
3
3
|
`)}async function generatePathIndex(entries,outputPath,options){const prefix=options.prefix??"",extensions=options.extensions??[".ts"],found=new Map,moduleSpecifier=defaultsModuleSpecifier();for(const entry of entries){const dir=typeof entry==="string"?entry:entry.dir,recursive=typeof entry==="string"?!0:entry.recursive;let files=[];try{for(const extension of extensions){const pattern=recursive?`${dir}/**/*${extension}`:`${dir}/*${extension}`;files.push(...globSync(pattern).sort())}}catch{continue}const rank=(file)=>extensions.findIndex((extension)=>file.endsWith(extension));files=files.sort((left,right)=>{const byRank=rank(left)-rank(right);if(byRank!==0)return byRank;return left<right?-1:left>right?1:0});for(const file of files){const basename=file.split("/").pop()??"";if(basename.endsWith(".d.ts")||basename.endsWith(".test.ts")||basename.endsWith(".spec.ts")||basename==="index.ts")continue;const extension=extensions.find((candidate)=>file.endsWith(candidate))??"",key=prefix+relative(dir,file).slice(0,extension.length?-extension.length:void 0);if(found.has(key))continue;found.set(key,moduleSpecifier(file,outputPath)??relative(dirname(outputPath),file).replace(/\\/g,"/"))}}const lines=["// Generated by bun-plugin-auto-imports","//","// Name to package export or relative file. The resolvers read it, and the name","// types are `keyof` over it - so a name that type-checks is a name that","// resolves. Values are paths rather than import thunks on purpose: thunks","// would make every compilation that touches a name resolve every module.",`export const ${options.exportName} = {`,...[...found.entries()].map(([key,file])=>` '${key}': '${file}',`),"} as const",""];await writeGeneratedFile(outputPath,lines.join(`
|
|
4
|
-
`))}export function autoImportSourceDirs(){return existingDirs([path.resourcesPath("functions"),frameworkDefaultsDir("functions"),path.userModelsPath(),...resolveDefaultModelDirs(),path.userJobsPath(),frameworkDefaultsDir("app/Jobs"),...packageJobDirs(),path.userControllersPath(),frameworkDefaultsDir("app/Controllers"),path.appPath("Actions"),frameworkDefaultsDir("app/Actions"),path.appPath("Listeners"),frameworkDefaultsDir("app/Listeners"),path.appPath("Policies"),frameworkDefaultsDir("app/Policies"),path.appPath("Middleware"),frameworkDefaultsDir("app/Middleware"),path.resourcesPath("emails"),frameworkDefaultsDir("resources/emails")])}export function autoImportsAreStale(){const manifest=path.storagePath("framework/auto-imports/functions.ts");if(!existsSync(manifest))return!0;let manifestTime;try{manifestTime=statSync(manifest).mtimeMs}catch{return!0}const discovered=path.storagePath("framework/discovered-packages.json");try{if(existsSync(discovered)&&statSync(discovered).mtimeMs>manifestTime)return!0}catch{}for(const dir of autoImportSourceDirs()){if(!existsSync(dir))continue;try{if(statSync(dir).mtimeMs>manifestTime)return!0;for(const file of globSync(`${dir}/**/*.ts`,{ignore:["**/*.d.ts"]}))if(statSync(file).mtimeMs>manifestTime)return!0}catch{continue}}return
|
|
4
|
+
`))}export function autoImportSourceDirs(){return existingDirs([path.resourcesPath("functions"),frameworkDefaultsDir("functions"),path.userModelsPath(),...resolveDefaultModelDirs(),path.userJobsPath(),frameworkDefaultsDir("app/Jobs"),...packageJobDirs(),path.userControllersPath(),frameworkDefaultsDir("app/Controllers"),path.appPath("Actions"),frameworkDefaultsDir("app/Actions"),path.appPath("Listeners"),frameworkDefaultsDir("app/Listeners"),path.appPath("Policies"),frameworkDefaultsDir("app/Policies"),path.appPath("Middleware"),frameworkDefaultsDir("app/Middleware"),path.resourcesPath("emails"),frameworkDefaultsDir("resources/emails")])}export function autoImportsAreStale(){const manifest=path.storagePath("framework/auto-imports/functions.ts");if(!existsSync(manifest))return!0;let manifestTime;try{manifestTime=statSync(manifest).mtimeMs}catch{return!0}const discovered=path.storagePath("framework/discovered-packages.json");try{if(existsSync(discovered)&&statSync(discovered).mtimeMs>manifestTime)return!0}catch{}for(const dir of autoImportSourceDirs()){if(!existsSync(dir))continue;try{if(statSync(dir).mtimeMs>manifestTime)return!0;for(const file of globSync(`${dir}/**/*.ts`,{ignore:["**/*.d.ts"]}))if(statSync(file).mtimeMs>manifestTime)return!0}catch{continue}}return recordedSourceFingerprint()!==autoImportSourceFingerprint()}export function autoImportSourceFingerprint(){const root=path.projectPath(),files=[];for(const dir of autoImportSourceDirs())for(const file of globSync(`${dir}/**/*.ts`,{ignore:["**/*.d.ts"]}))files.push(relative(root,file));files.sort();let packages="";try{const manifest=JSON.parse(readFileSync(path.storagePath("framework/discovered-packages.json"),"utf8"));packages=JSON.stringify(Object.keys(manifest.packages??{}).sort().map((name)=>[name,manifest.packages[name]]))}catch{}return new Bun.CryptoHasher("sha256").update(files.join(`
|
|
5
|
+
`)).update("\x00").update(packages).digest("hex")}function recordedSourceFingerprint(){try{return JSON.parse(readFileSync(path.storagePath("framework/auto-imports/sources.json"),"utf8")).fingerprint}catch{return}}export async function generateAutoImportFiles(options={}){const moduleSpecifier=defaultsModuleSpecifier(),userFunctionsPath=path.resourcesPath("functions"),defaultFunctionsPath=frameworkDefaultsDir("functions"),functionsPath=userFunctionsPath,outputDir=path.storagePath("framework/auto-imports"),userModelsPath=path.userModelsPath(),defaultModelDirs=resolveDefaultModelDirs(),[defaultsRoot,...enabledSubdirs]=defaultModelDirs,userJobsPath=path.userJobsPath(),userControllersPath=path.userControllersPath(),defaultControllersPath=frameworkDefaultsDir("app/Controllers");await Bun.write(`${outputDir}/.gitkeep`,"");const functionsIndexPath=`${outputDir}/functions.ts`;await generateRuntimeIndex(existingDirs([userFunctionsPath,defaultFunctionsPath]),functionsIndexPath,{moduleSpecifier});const modelsIndexPath=`${outputDir}/models.ts`,modelScan=[userModelsPath,...packageModelDirs().map((dir)=>({dir,recursive:!0})),...defaultsRoot?[{dir:defaultsRoot,recursive:!1}]:[],...defaultModelDirs.slice(1).map((d)=>({dir:d,recursive:!0}))];await generateDefineModelIndex(modelScan,modelsIndexPath);const jobsIndexPath=`${outputDir}/jobs.ts`;await generateDefineModelIndex(existingDirs([userJobsPath,frameworkDefaultsDir("app/Jobs"),...packageJobDirs()]),jobsIndexPath);await generatePathIndex(existingDirs([path.appPath("Actions"),frameworkDefaultsDir("app/Actions")]),`${outputDir}/actions.ts`,{exportName:"actions",prefix:"Actions/"});await generatePathIndex(existingDirs([path.appPath("Listeners"),frameworkDefaultsDir("app/Listeners")]),`${outputDir}/listeners.ts`,{exportName:"listeners"});await generatePathIndex(existingDirs([path.appPath("Policies"),frameworkDefaultsDir("app/Policies")]),`${outputDir}/policies.ts`,{exportName:"policies"});await generatePathIndex(existingDirs([path.appPath("Middleware"),frameworkDefaultsDir("app/Middleware")]),`${outputDir}/middleware.ts`,{exportName:"middleware"});await generatePathIndex(existingDirs([path.resourcesPath("emails"),frameworkDefaultsDir("resources/emails")]),`${outputDir}/emails.ts`,{exportName:"emails",extensions:[".stx",".html"]});const controllersIndexPath=`${outputDir}/controllers.ts`;await generateDefineModelIndex(existingDirs([userControllersPath,defaultControllersPath]),controllersIndexPath);const combinedContent=combinedBarrel(COMBINED_BARRELS.map((name)=>({name,source:existsSync(`${outputDir}/${name}.ts`)?readFileSync(`${outputDir}/${name}.ts`,"utf8"):""})));await writeGeneratedFile(`${outputDir}/index.ts`,combinedContent);await writeGeneratedFile(`${outputDir}/sources.json`,`${JSON.stringify({fingerprint:autoImportSourceFingerprint()},null,2)}
|
|
6
|
+
`);const globalsPath=`${outputDir}/globals.ts`;await generateGlobalsScript(existingDirs([functionsPath]),globalsPath,`${outputDir}/index.ts`,{moduleSpecifier});if(options.declarations!==!1){await generateServerAutoImportTypes();const pruned=await pruneBrowserAutoImportTypes();if(pruned.length>0)log.debug(`[auto-imports] dropped ${pruned.length} browser globals that nothing injects`);await invalidateTypeScriptBuildInfo()}log.debug("Auto-import files generated successfully")}const COMBINED_BARRELS=["functions","models","jobs","controllers"];export function barrelExportNames(source){const names=new Map;for(const line of source.split(`
|
|
5
7
|
`)){const match=/^export (type )?\{([^}]*)\} from /.exec(line.trim());if(!match)continue;const lineIsType=Boolean(match[1]);for(const raw of match[2].split(",")){let specifier=raw.trim();if(!specifier)continue;const specifierIsType=specifier.startsWith("type ");if(specifierIsType)specifier=specifier.slice(5).trim();const name=specifier.split(/\s+as\s+/).pop().trim(),typeOnly=lineIsType||specifierIsType,previous=names.get(name);names.set(name,{typeOnly:typeOnly&&(previous?.typeOnly??!0)})}}return names}export function combinedBarrel(barrels){const lines=["// Generated by bun-plugin-auto-imports",...barrels.map((b)=>`export * from './${b.name}'`)],owners=new Map,exported=barrels.map((b)=>({name:b.name,names:barrelExportNames(b.source)}));for(const barrel of exported)for(const name of barrel.names.keys())owners.set(name,[...owners.get(name)??[],barrel.name]);const winners=new Map;for(const[name,from]of[...owners].sort(([a],[b])=>a.localeCompare(b))){if(from.length<2)continue;const winner=from.at(-1),typeOnly=exported.find((b)=>b.name===winner).names.get(name).typeOnly,entry=winners.get(winner)??{value:[],type:[]};entry[typeOnly?"type":"value"].push(name);winners.set(winner,entry)}if(winners.size>0){lines.push("");lines.push("// Names more than one barrel exports, which `export *` would drop (TS2308).");for(const barrel of barrels){const entry=winners.get(barrel.name);if(entry?.value.length)lines.push(`export { ${entry.value.join(", ")} } from './${barrel.name}'`);if(entry?.type.length)lines.push(`export type { ${entry.type.join(", ")} } from './${barrel.name}'`)}}return`${lines.join(`
|
|
6
8
|
`)}
|
|
7
9
|
`}async function invalidateTypeScriptBuildInfo(){const cacheDir=path.storagePath("framework/.cache/typescript");try{const{readdirSync,rmSync}=await import("node:fs");for(const entry of readdirSync(cacheDir)){if(!entry.endsWith(".tsbuildinfo"))continue;rmSync(`${cacheDir}/${entry}`,{force:!0});log.debug(`[auto-imports] dropped stale ${entry}`)}}catch{}}export function initiateImports(){const moduleSpecifier=defaultsModuleSpecifier(),functionsPath=path.resourcesPath("functions"),defaultFunctionsPath=frameworkDefaultsDir("functions"),userModelsPath=path.userModelsPath(),defaultModelDirs=resolveDefaultModelDirs(),[defaultsRoot,...enabledSubdirs]=defaultModelDirs,userJobsPath=path.userJobsPath(),userControllersPath=path.userControllersPath(),defaultControllersPath=frameworkDefaultsDir("app/Controllers"),defineModelExports=[...scanDefineModelExports(userModelsPath),...packageModelDirs().flatMap((dir)=>scanDefineModelExports(dir)),...defaultsRoot?scanDefineModelExports(defaultsRoot,{recursive:!1}):[],...enabledSubdirs.flatMap((d)=>scanDefineModelExports(d))],seenJobs=new Set,jobExports=[...scanDefineModelExports(userJobsPath),...packageJobDirs().flatMap((dir)=>scanDefineModelExports(dir))].filter((exp)=>{if(seenJobs.has(exp.name))return!1;seenJobs.add(exp.name);return!0}),seen=new Set,uniqueDefineModelExports=defineModelExports.filter((exp)=>{if(seen.has(exp.name))return!1;seen.add(exp.name);return!0}),dtsDir=dirname(path.storagePath("framework/types/server-auto-imports.d.ts")),defineModelImports=uniqueDefineModelExports.map((exp)=>({from:declarationModuleSpecifier(exp.file,`${dtsDir}/server-auto-imports.d.ts`,moduleSpecifier),name:"default",as:exp.name})),jobImports=jobExports.map((exp)=>({from:declarationModuleSpecifier(exp.file,`${dtsDir}/server-auto-imports.d.ts`,moduleSpecifier),name:"default",as:exp.name})),controllerExports=[...scanDefineModelExports(userControllersPath),...defaultControllersPath?scanDefineModelExports(defaultControllersPath):[]],seenControllers=new Set,controllerImports=controllerExports.filter((exp)=>{if(seenControllers.has(exp.name))return!1;seenControllers.add(exp.name);return!0}).map((exp)=>({from:declarationModuleSpecifier(exp.file,`${dtsDir}/server-auto-imports.d.ts`,moduleSpecifier),name:"default",as:exp.name})),options={moduleSpecifier,dts:path.storagePath("framework/types/server-auto-imports.d.ts"),imports:[...primitiveAutoImportEntries(),...defineModelImports,...jobImports,...controllerImports],dirs:existingDirs([functionsPath,defaultFunctionsPath]),eslint:{enabled:!0,filepath:path.storagePath("framework/server-auto-imports.json")}};plugin(autoImports(options));generateAutoImportFiles().catch((err)=>{console.error("[Server] Failed to generate auto-import files:",err)})}export async function generateServerAutoImportTypes(){const moduleSpecifier=defaultsModuleSpecifier(),seen=new Set,valueExports=[...barrelExports("models"),...barrelExports("jobs"),...barrelExports("controllers"),...await ormModelGlobals()].filter((exp)=>!GLOBAL_SHADOW_BLOCKLIST.has(exp.name)).filter((exp)=>{if(seen.has(exp.name))return!1;seen.add(exp.name);return!0}),outputPath=path.storagePath("framework/types/server-auto-imports.d.ts"),declaredValues=new Set(valueExports.map((exp)=>exp.name)),lines=["// Generated by Stacks server auto-imports","// This file is regenerated automatically when the API starts.","export {}","declare global {"];for(const{from,name,as}of primitiveAutoImportEntries())if(!declaredValues.has(as))lines.push(` const ${as}: typeof import('${from}')['${name}']`);for(const exp of valueExports){if(!exp.isDefault){lines.push(` const ${exp.name}: typeof import('${exp.file}')['${exp.name}']`);continue}const relativePath=declarationModuleSpecifier(exp.file,outputPath,moduleSpecifier);lines.push(` const ${exp.name}: typeof import('${relativePath}')['default']`)}lines.push("}","");await writeGeneratedFile(outputPath,lines.join(`
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/server",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.75.
|
|
5
|
+
"version": "0.75.263",
|
|
6
6
|
"description": "Local development and production-ready.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -58,21 +58,21 @@
|
|
|
58
58
|
"prepublishOnly": "bun run build"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@stacksjs/auth": "0.75.
|
|
61
|
+
"@stacksjs/auth": "0.75.263",
|
|
62
62
|
"@stacksjs/bun-router": "^0.1.24",
|
|
63
|
-
"@stacksjs/config": "0.75.
|
|
64
|
-
"@stacksjs/events": "0.75.
|
|
65
|
-
"@stacksjs/i18n": "0.75.
|
|
66
|
-
"@stacksjs/logging": "0.75.
|
|
67
|
-
"@stacksjs/orm": "0.75.
|
|
68
|
-
"@stacksjs/path": "0.75.
|
|
69
|
-
"@stacksjs/payments": "0.75.
|
|
70
|
-
"@stacksjs/router": "0.75.
|
|
71
|
-
"@stacksjs/storage": "0.75.
|
|
63
|
+
"@stacksjs/config": "0.75.263",
|
|
64
|
+
"@stacksjs/events": "0.75.263",
|
|
65
|
+
"@stacksjs/i18n": "0.75.263",
|
|
66
|
+
"@stacksjs/logging": "0.75.263",
|
|
67
|
+
"@stacksjs/orm": "0.75.263",
|
|
68
|
+
"@stacksjs/path": "0.75.263",
|
|
69
|
+
"@stacksjs/payments": "0.75.263",
|
|
70
|
+
"@stacksjs/router": "0.75.263",
|
|
71
|
+
"@stacksjs/storage": "0.75.263",
|
|
72
72
|
"bun-plugin-auto-imports": "^0.4.4"
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
75
|
-
"@stacksjs/validation": "0.75.
|
|
75
|
+
"@stacksjs/validation": "0.75.263",
|
|
76
76
|
"better-dx": "^0.2.24"
|
|
77
77
|
}
|
|
78
78
|
}
|