@boon4681/giri 0.0.2-alpha-8 → 0.0.3-alpha-1
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/adapters/hono.js +13 -13
- package/dist/adapters/hono.js.map +1 -1
- package/dist/cli.js +338 -155
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +179 -80
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -46,13 +46,7 @@ var init_es5 = __esm({
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
// src/generator/schema/program.ts
|
|
49
|
-
function
|
|
50
|
-
return {
|
|
51
|
-
...options,
|
|
52
|
-
types: []
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
function createSchemaProgram(paths, routeFiles, programOptions = {}) {
|
|
49
|
+
function createSchemaProgram(paths, routeFiles) {
|
|
56
50
|
let options = { ...DEFAULT_OPTIONS };
|
|
57
51
|
const configPath = import_typescript2.default.findConfigFile(paths.cwd, import_typescript2.default.sys.fileExists, "tsconfig.json");
|
|
58
52
|
if (configPath) {
|
|
@@ -65,9 +59,6 @@ function createSchemaProgram(paths, routeFiles, programOptions = {}) {
|
|
|
65
59
|
options = { ...parsed.options, noEmit: true };
|
|
66
60
|
}
|
|
67
61
|
}
|
|
68
|
-
if (programOptions.lean) {
|
|
69
|
-
options = leanOptions(options);
|
|
70
|
-
}
|
|
71
62
|
return import_typescript2.default.createProgram(routeFiles, options);
|
|
72
63
|
}
|
|
73
64
|
var import_typescript2, DEFAULT_OPTIONS;
|
|
@@ -410,9 +401,9 @@ var init_schema = __esm({
|
|
|
410
401
|
|
|
411
402
|
// src/cli.ts
|
|
412
403
|
var import_node_child_process = require("child_process");
|
|
413
|
-
var
|
|
414
|
-
var
|
|
415
|
-
var
|
|
404
|
+
var import_node_fs12 = require("fs");
|
|
405
|
+
var import_promises5 = require("fs/promises");
|
|
406
|
+
var import_node_path17 = require("path");
|
|
416
407
|
var prompts = __toESM(require("@clack/prompts"));
|
|
417
408
|
|
|
418
409
|
// src/app.ts
|
|
@@ -823,8 +814,11 @@ async function buildGiriApp(config, options = {}) {
|
|
|
823
814
|
const routes = await scanRoutes(paths.routesDir);
|
|
824
815
|
const app = config.adapter.createApp();
|
|
825
816
|
ensureGiriAliasResolver(paths.outDir);
|
|
826
|
-
|
|
827
|
-
|
|
817
|
+
if (options.lazy && (!options.loaderRegistered || !options.aliasResolverRegistered)) {
|
|
818
|
+
throw new Error("Lazy route loading requires persistent loader and alias registrations.");
|
|
819
|
+
}
|
|
820
|
+
const loader = options.loaderRegistered ? void 0 : await safeRegister();
|
|
821
|
+
const unregisterAliasResolver = options.aliasResolverRegistered ? void 0 : registerAliasResolver(config.alias, paths.cwd);
|
|
828
822
|
try {
|
|
829
823
|
const dirty = options.dirty;
|
|
830
824
|
const forceReload = dirty === void 0;
|
|
@@ -836,7 +830,7 @@ async function buildGiriApp(config, options = {}) {
|
|
|
836
830
|
}
|
|
837
831
|
return sharedCache.get(file);
|
|
838
832
|
};
|
|
839
|
-
|
|
833
|
+
const runtimeFor = (route) => {
|
|
840
834
|
const routeModule = loadModule(route.file, isDirty(route.file));
|
|
841
835
|
if (typeof routeModule.handle !== "function") {
|
|
842
836
|
throw new Error(`${route.file} must export a named handle function.`);
|
|
@@ -845,7 +839,7 @@ async function buildGiriApp(config, options = {}) {
|
|
|
845
839
|
(file) => normalizeMiddleware(loadShared(file).middleware, file)
|
|
846
840
|
);
|
|
847
841
|
const verbMiddleware = normalizeMiddleware(routeModule.middleware, route.file);
|
|
848
|
-
|
|
842
|
+
return {
|
|
849
843
|
method: route.method,
|
|
850
844
|
path: route.path,
|
|
851
845
|
handle: routeModule.handle,
|
|
@@ -853,19 +847,45 @@ async function buildGiriApp(config, options = {}) {
|
|
|
853
847
|
input: routeInput(routeModule, route.file),
|
|
854
848
|
services: options.services,
|
|
855
849
|
cookieSecret: config.cookieSecret
|
|
850
|
+
};
|
|
851
|
+
};
|
|
852
|
+
for (const route of routes) {
|
|
853
|
+
if (!options.lazy) {
|
|
854
|
+
config.adapter.register(app, runtimeFor(route));
|
|
855
|
+
continue;
|
|
856
|
+
}
|
|
857
|
+
let runtime;
|
|
858
|
+
const getRuntime = () => {
|
|
859
|
+
runtime ??= runtimeFor(route);
|
|
860
|
+
return runtime;
|
|
861
|
+
};
|
|
862
|
+
config.adapter.register(app, {
|
|
863
|
+
method: route.method,
|
|
864
|
+
path: route.path,
|
|
865
|
+
get handle() {
|
|
866
|
+
return getRuntime().handle;
|
|
867
|
+
},
|
|
868
|
+
get middleware() {
|
|
869
|
+
return getRuntime().middleware;
|
|
870
|
+
},
|
|
871
|
+
get input() {
|
|
872
|
+
return getRuntime().input;
|
|
873
|
+
},
|
|
874
|
+
services: options.services,
|
|
875
|
+
cookieSecret: config.cookieSecret
|
|
856
876
|
});
|
|
857
877
|
}
|
|
858
878
|
} finally {
|
|
859
|
-
unregisterAliasResolver();
|
|
860
|
-
unregister();
|
|
879
|
+
unregisterAliasResolver?.();
|
|
880
|
+
loader?.unregister();
|
|
861
881
|
}
|
|
862
882
|
return { app, routes, paths };
|
|
863
883
|
}
|
|
864
884
|
|
|
865
885
|
// src/generator/sync.ts
|
|
866
|
-
var
|
|
867
|
-
var
|
|
868
|
-
var
|
|
886
|
+
var import_node_fs8 = require("fs");
|
|
887
|
+
var import_promises4 = require("fs/promises");
|
|
888
|
+
var import_node_path12 = require("path");
|
|
869
889
|
|
|
870
890
|
// src/generator/app-types.ts
|
|
871
891
|
var import_node_fs4 = require("fs");
|
|
@@ -1812,6 +1832,103 @@ async function writeTsConfig(paths, config) {
|
|
|
1812
1832
|
});
|
|
1813
1833
|
}
|
|
1814
1834
|
|
|
1835
|
+
// src/generator/cache.ts
|
|
1836
|
+
var import_node_crypto = require("crypto");
|
|
1837
|
+
var import_node_fs7 = require("fs");
|
|
1838
|
+
var import_promises3 = require("fs/promises");
|
|
1839
|
+
var import_node_path11 = require("path");
|
|
1840
|
+
var import_tinyglobby2 = require("tinyglobby");
|
|
1841
|
+
var CACHE_VERSION = 1;
|
|
1842
|
+
var SYNC_CACHE_NAME = ".sync-cache.json";
|
|
1843
|
+
function stableConfig(config) {
|
|
1844
|
+
const alias = Object.entries(config.alias ?? {}).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => [key, Array.isArray(value) ? [...value] : value]);
|
|
1845
|
+
return { alias, outDir: config.outDir ?? ".giri" };
|
|
1846
|
+
}
|
|
1847
|
+
async function syncFingerprint(config, paths) {
|
|
1848
|
+
const outRelative = slash((0, import_node_path11.relative)(paths.cwd, paths.outDir));
|
|
1849
|
+
const ignore = ["**/node_modules/**", "**/.git/**"];
|
|
1850
|
+
if (outRelative && !outRelative.startsWith("..")) {
|
|
1851
|
+
ignore.push(`${outRelative}/**`);
|
|
1852
|
+
}
|
|
1853
|
+
const files = await (0, import_tinyglobby2.glob)([
|
|
1854
|
+
"src/**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs,json}",
|
|
1855
|
+
"giri.config.{ts,js,mts,cts,mjs,cjs}",
|
|
1856
|
+
"tsconfig*.json",
|
|
1857
|
+
"package.json",
|
|
1858
|
+
"package-lock.json",
|
|
1859
|
+
"npm-shrinkwrap.json",
|
|
1860
|
+
"yarn.lock",
|
|
1861
|
+
"pnpm-lock.yaml",
|
|
1862
|
+
"bun.lock",
|
|
1863
|
+
"bun.lockb"
|
|
1864
|
+
], {
|
|
1865
|
+
cwd: paths.cwd,
|
|
1866
|
+
absolute: false,
|
|
1867
|
+
onlyFiles: true,
|
|
1868
|
+
dot: true,
|
|
1869
|
+
ignore
|
|
1870
|
+
});
|
|
1871
|
+
const hash = (0, import_node_crypto.createHash)("sha256");
|
|
1872
|
+
hash.update(JSON.stringify(stableConfig(config)));
|
|
1873
|
+
for (const file of files.sort()) {
|
|
1874
|
+
hash.update("\0");
|
|
1875
|
+
hash.update(slash(file));
|
|
1876
|
+
hash.update("\0");
|
|
1877
|
+
hash.update(await (0, import_promises3.readFile)((0, import_node_path11.resolve)(paths.cwd, file)));
|
|
1878
|
+
}
|
|
1879
|
+
return hash.digest("hex");
|
|
1880
|
+
}
|
|
1881
|
+
function cachePath(paths) {
|
|
1882
|
+
return (0, import_node_path11.join)(paths.outDir, SYNC_CACHE_NAME);
|
|
1883
|
+
}
|
|
1884
|
+
function serializePath(paths, file) {
|
|
1885
|
+
return slash((0, import_node_path11.relative)(paths.cwd, file));
|
|
1886
|
+
}
|
|
1887
|
+
function deserializePath(paths, file) {
|
|
1888
|
+
return slash((0, import_node_path11.resolve)(paths.cwd, file.split("/").join(import_node_path11.sep)));
|
|
1889
|
+
}
|
|
1890
|
+
function serializeMap(paths, values) {
|
|
1891
|
+
return [...values].map(([file, value]) => [serializePath(paths, file), value]);
|
|
1892
|
+
}
|
|
1893
|
+
function deserializeMap(paths, values) {
|
|
1894
|
+
return new Map(values.map(([file, value]) => [deserializePath(paths, file), value]));
|
|
1895
|
+
}
|
|
1896
|
+
async function readSyncCache(paths, fingerprint) {
|
|
1897
|
+
const file = cachePath(paths);
|
|
1898
|
+
if (!(0, import_node_fs7.existsSync)(file)) {
|
|
1899
|
+
return void 0;
|
|
1900
|
+
}
|
|
1901
|
+
try {
|
|
1902
|
+
const cache = JSON.parse(await (0, import_promises3.readFile)(file, "utf8"));
|
|
1903
|
+
if (cache.version !== CACHE_VERSION || cache.fingerprint !== fingerprint) {
|
|
1904
|
+
return void 0;
|
|
1905
|
+
}
|
|
1906
|
+
return {
|
|
1907
|
+
responsesByFile: deserializeMap(paths, cache.data.responsesByFile),
|
|
1908
|
+
inputsByFile: deserializeMap(paths, cache.data.inputsByFile),
|
|
1909
|
+
securityByFile: deserializeMap(paths, cache.data.securityByFile),
|
|
1910
|
+
hiddenFiles: new Set(cache.data.hiddenFiles.map((entry) => deserializePath(paths, entry))),
|
|
1911
|
+
openapiByFile: deserializeMap(paths, cache.data.openapiByFile)
|
|
1912
|
+
};
|
|
1913
|
+
} catch {
|
|
1914
|
+
return void 0;
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
async function writeSyncCache(paths, fingerprint, data) {
|
|
1918
|
+
const cache = {
|
|
1919
|
+
version: CACHE_VERSION,
|
|
1920
|
+
fingerprint,
|
|
1921
|
+
data: {
|
|
1922
|
+
responsesByFile: serializeMap(paths, data.responsesByFile),
|
|
1923
|
+
inputsByFile: serializeMap(paths, data.inputsByFile),
|
|
1924
|
+
securityByFile: serializeMap(paths, data.securityByFile),
|
|
1925
|
+
hiddenFiles: [...data.hiddenFiles].map((file) => serializePath(paths, file)),
|
|
1926
|
+
openapiByFile: serializeMap(paths, data.openapiByFile)
|
|
1927
|
+
}
|
|
1928
|
+
};
|
|
1929
|
+
await writeJson(cachePath(paths), cache);
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1815
1932
|
// src/generator/sync.ts
|
|
1816
1933
|
async function typeFolders(paths, routes) {
|
|
1817
1934
|
const verbsByDir = /* @__PURE__ */ new Map();
|
|
@@ -1838,57 +1955,17 @@ async function extractResponses(paths, routes) {
|
|
|
1838
1955
|
try {
|
|
1839
1956
|
const { createSchemaProgram: createSchemaProgram2, extractRouteResponses: extractRouteResponses2 } = await Promise.resolve().then(() => (init_schema(), schema_exports));
|
|
1840
1957
|
const files = [...new Set(routes.map((route) => route.file))];
|
|
1841
|
-
const appTypes = (0,
|
|
1842
|
-
const roots = (0,
|
|
1843
|
-
const program = createSchemaProgram2(paths, roots
|
|
1844
|
-
const fallbackFiles = [];
|
|
1958
|
+
const appTypes = (0, import_node_path12.join)(paths.outDir, "types", "app.d.ts");
|
|
1959
|
+
const roots = (0, import_node_fs8.existsSync)(appTypes) ? [...files, appTypes] : files;
|
|
1960
|
+
const program = createSchemaProgram2(paths, roots);
|
|
1845
1961
|
for (const file of files) {
|
|
1846
|
-
|
|
1847
|
-
byFile.set(file, responses);
|
|
1848
|
-
if (hasLooseResponseSchema(responses)) {
|
|
1849
|
-
fallbackFiles.push(file);
|
|
1850
|
-
}
|
|
1851
|
-
}
|
|
1852
|
-
if (fallbackFiles.length > 0) {
|
|
1853
|
-
const fullProgram = createSchemaProgram2(
|
|
1854
|
-
paths,
|
|
1855
|
-
(0, import_node_fs7.existsSync)(appTypes) ? [...fallbackFiles, appTypes] : fallbackFiles
|
|
1856
|
-
);
|
|
1857
|
-
for (const file of fallbackFiles) {
|
|
1858
|
-
byFile.set(file, extractRouteResponses2(fullProgram, file));
|
|
1859
|
-
}
|
|
1962
|
+
byFile.set(file, extractRouteResponses2(program, file));
|
|
1860
1963
|
}
|
|
1861
1964
|
} catch (error) {
|
|
1862
1965
|
console.warn(`giri: skipped response schema generation (${error.message}).`);
|
|
1863
1966
|
}
|
|
1864
1967
|
return byFile;
|
|
1865
1968
|
}
|
|
1866
|
-
function isLooseSchema(value) {
|
|
1867
|
-
if (!value || typeof value !== "object") {
|
|
1868
|
-
return false;
|
|
1869
|
-
}
|
|
1870
|
-
const schema = value;
|
|
1871
|
-
const keys = Object.keys(schema);
|
|
1872
|
-
if (keys.length === 0) {
|
|
1873
|
-
return true;
|
|
1874
|
-
}
|
|
1875
|
-
if (typeof schema.$ref === "string") {
|
|
1876
|
-
return false;
|
|
1877
|
-
}
|
|
1878
|
-
if (Array.isArray(schema.anyOf) && schema.anyOf.some(isLooseSchema)) {
|
|
1879
|
-
return true;
|
|
1880
|
-
}
|
|
1881
|
-
if (schema.items && isLooseSchema(schema.items)) {
|
|
1882
|
-
return true;
|
|
1883
|
-
}
|
|
1884
|
-
if (schema.properties && typeof schema.properties === "object") {
|
|
1885
|
-
return Object.values(schema.properties).some(isLooseSchema);
|
|
1886
|
-
}
|
|
1887
|
-
return false;
|
|
1888
|
-
}
|
|
1889
|
-
function hasLooseResponseSchema(responses) {
|
|
1890
|
-
return responses.responses.some((response) => isLooseSchema(response.schema));
|
|
1891
|
-
}
|
|
1892
1969
|
async function extractMeta(config, paths, routes) {
|
|
1893
1970
|
const inputsByFile = /* @__PURE__ */ new Map();
|
|
1894
1971
|
const securityByFile = /* @__PURE__ */ new Map();
|
|
@@ -1921,28 +1998,44 @@ async function extractMeta(config, paths, routes) {
|
|
|
1921
1998
|
async function syncProject(config, options = {}) {
|
|
1922
1999
|
const paths = resolveGiriPaths(config, options.cwd);
|
|
1923
2000
|
assertSafeOutDir(paths);
|
|
1924
|
-
const hadOutDir = (0,
|
|
2001
|
+
const hadOutDir = (0, import_node_fs8.existsSync)(paths.outDir);
|
|
1925
2002
|
const routes = await scanRoutes(paths.routesDir);
|
|
1926
2003
|
const folders = await typeFolders(paths, routes);
|
|
1927
|
-
await (
|
|
2004
|
+
const fingerprint = await syncFingerprint(config, paths);
|
|
2005
|
+
const cached = await readSyncCache(paths, fingerprint);
|
|
2006
|
+
const generatedFiles = [
|
|
2007
|
+
(0, import_node_path12.join)(paths.outDir, "tsconfig.json"),
|
|
2008
|
+
(0, import_node_path12.join)(paths.outDir, "manifest.json"),
|
|
2009
|
+
(0, import_node_path12.join)(paths.outDir, "openapi.json"),
|
|
2010
|
+
(0, import_node_path12.join)(paths.outDir, "routes.d.ts"),
|
|
2011
|
+
(0, import_node_path12.join)(paths.outDir, "types", "app.d.ts"),
|
|
2012
|
+
...folders.map((folder) => typeFilePath(paths, folder.dir))
|
|
2013
|
+
];
|
|
2014
|
+
if (cached && generatedFiles.every(import_node_fs8.existsSync)) {
|
|
2015
|
+
return { paths, routes, folders, data: cached };
|
|
2016
|
+
}
|
|
2017
|
+
await (0, import_promises4.mkdir)(paths.outDir, { recursive: true });
|
|
1928
2018
|
await writeParamTypes(paths, folders);
|
|
1929
2019
|
await writeRouteTypes(paths, routes);
|
|
1930
2020
|
await writeAppTypes(paths);
|
|
1931
2021
|
await writeTsConfig(paths, config);
|
|
1932
|
-
const
|
|
1933
|
-
|
|
1934
|
-
|
|
2022
|
+
const data = cached ?? {
|
|
2023
|
+
responsesByFile: await extractResponses(paths, routes),
|
|
2024
|
+
...await extractMeta(config, paths, routes)
|
|
2025
|
+
};
|
|
1935
2026
|
await writeManifest(paths, routes, data);
|
|
1936
2027
|
await writeOpenApi(paths, routes, data);
|
|
2028
|
+
await writeSyncCache(paths, fingerprint, data);
|
|
1937
2029
|
if (hadOutDir) {
|
|
1938
2030
|
await pruneDir(
|
|
1939
2031
|
paths.outDir,
|
|
1940
2032
|
/* @__PURE__ */ new Set([
|
|
1941
|
-
(0,
|
|
1942
|
-
(0,
|
|
1943
|
-
(0,
|
|
1944
|
-
(0,
|
|
1945
|
-
(0,
|
|
2033
|
+
(0, import_node_path12.join)(paths.outDir, "tsconfig.json"),
|
|
2034
|
+
(0, import_node_path12.join)(paths.outDir, "manifest.json"),
|
|
2035
|
+
(0, import_node_path12.join)(paths.outDir, "openapi.json"),
|
|
2036
|
+
(0, import_node_path12.join)(paths.outDir, "routes.d.ts"),
|
|
2037
|
+
(0, import_node_path12.join)(paths.outDir, SYNC_CACHE_NAME),
|
|
2038
|
+
(0, import_node_path12.join)(paths.outDir, "types", "app.d.ts"),
|
|
1946
2039
|
...folders.map((folder) => typeFilePath(paths, folder.dir))
|
|
1947
2040
|
])
|
|
1948
2041
|
);
|
|
@@ -1951,43 +2044,122 @@ async function syncProject(config, options = {}) {
|
|
|
1951
2044
|
}
|
|
1952
2045
|
|
|
1953
2046
|
// src/generator/watch.ts
|
|
1954
|
-
var
|
|
1955
|
-
var
|
|
2047
|
+
var import_node_fs10 = require("fs");
|
|
2048
|
+
var import_node_path15 = require("path");
|
|
1956
2049
|
|
|
1957
|
-
// src/loader/
|
|
1958
|
-
var
|
|
1959
|
-
var
|
|
1960
|
-
var
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
var
|
|
1964
|
-
|
|
2050
|
+
// src/loader/import-graph.ts
|
|
2051
|
+
var import_node_fs9 = require("fs");
|
|
2052
|
+
var import_node_path13 = require("path");
|
|
2053
|
+
var import_typescript5 = __toESM(require("typescript"));
|
|
2054
|
+
var import_tinyglobby3 = require("tinyglobby");
|
|
2055
|
+
var RESOLVE_EXTS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
2056
|
+
var JS_EXT = /\.(?:c|m)?jsx?$/;
|
|
2057
|
+
var toSlash = (path) => path.split(import_node_path13.sep).join("/");
|
|
2058
|
+
function probeFile(base) {
|
|
2059
|
+
if ((0, import_node_fs9.existsSync)(base) && (0, import_node_fs9.statSync)(base).isFile()) {
|
|
2060
|
+
return base;
|
|
2061
|
+
}
|
|
2062
|
+
for (const ext of RESOLVE_EXTS) {
|
|
2063
|
+
const candidate = base + ext;
|
|
2064
|
+
if ((0, import_node_fs9.existsSync)(candidate)) {
|
|
2065
|
+
return candidate;
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
for (const ext of RESOLVE_EXTS) {
|
|
2069
|
+
const candidate = (0, import_node_path13.join)(base, `index${ext}`);
|
|
2070
|
+
if ((0, import_node_fs9.existsSync)(candidate)) {
|
|
2071
|
+
return candidate;
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
return void 0;
|
|
2075
|
+
}
|
|
2076
|
+
function resolveSpecifier(specifier, fromFile, alias, cwd) {
|
|
2077
|
+
let target;
|
|
2078
|
+
if (specifier.startsWith(".")) {
|
|
2079
|
+
target = (0, import_node_path13.resolve)((0, import_node_path13.dirname)(fromFile), specifier);
|
|
2080
|
+
} else {
|
|
2081
|
+
const aliased = resolveAliasRequest(specifier, alias, cwd);
|
|
2082
|
+
if (aliased === void 0) {
|
|
2083
|
+
return void 0;
|
|
2084
|
+
}
|
|
2085
|
+
target = aliased;
|
|
2086
|
+
}
|
|
2087
|
+
const resolved = probeFile(target);
|
|
2088
|
+
if (resolved) {
|
|
2089
|
+
return resolved;
|
|
2090
|
+
}
|
|
2091
|
+
if (JS_EXT.test(target)) {
|
|
2092
|
+
return probeFile(target.replace(JS_EXT, ""));
|
|
2093
|
+
}
|
|
2094
|
+
return void 0;
|
|
2095
|
+
}
|
|
2096
|
+
function importSpecifiers(file) {
|
|
2097
|
+
let source;
|
|
2098
|
+
try {
|
|
2099
|
+
source = import_typescript5.default.createSourceFile(file, (0, import_node_fs9.readFileSync)(file, "utf8"), import_typescript5.default.ScriptTarget.Latest, false);
|
|
2100
|
+
} catch {
|
|
2101
|
+
return [];
|
|
2102
|
+
}
|
|
2103
|
+
const specifiers = [];
|
|
2104
|
+
const visit = (node) => {
|
|
2105
|
+
if ((import_typescript5.default.isImportDeclaration(node) || import_typescript5.default.isExportDeclaration(node)) && node.moduleSpecifier && import_typescript5.default.isStringLiteral(node.moduleSpecifier)) {
|
|
2106
|
+
specifiers.push(node.moduleSpecifier.text);
|
|
2107
|
+
} else if (import_typescript5.default.isImportEqualsDeclaration(node) && import_typescript5.default.isExternalModuleReference(node.moduleReference) && import_typescript5.default.isStringLiteralLike(node.moduleReference.expression)) {
|
|
2108
|
+
specifiers.push(node.moduleReference.expression.text);
|
|
2109
|
+
} else if (import_typescript5.default.isCallExpression(node)) {
|
|
2110
|
+
const isRequire = import_typescript5.default.isIdentifier(node.expression) && node.expression.text === "require";
|
|
2111
|
+
const isDynamicImport = node.expression.kind === import_typescript5.default.SyntaxKind.ImportKeyword;
|
|
2112
|
+
const [first] = node.arguments;
|
|
2113
|
+
if ((isRequire || isDynamicImport) && first && import_typescript5.default.isStringLiteralLike(first)) {
|
|
2114
|
+
specifiers.push(first.text);
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
import_typescript5.default.forEachChild(node, visit);
|
|
2118
|
+
};
|
|
2119
|
+
visit(source);
|
|
2120
|
+
return specifiers;
|
|
2121
|
+
}
|
|
2122
|
+
async function buildImportGraph(config, cwd) {
|
|
2123
|
+
const root = (0, import_node_path13.resolve)(cwd);
|
|
2124
|
+
const outDir = (0, import_node_path13.resolve)(root, config.outDir ?? ".giri") + import_node_path13.sep;
|
|
2125
|
+
const outRel = (0, import_node_path13.relative)(root, outDir).split(import_node_path13.sep).join("/").replace(/\/$/, "");
|
|
2126
|
+
const files = await (0, import_tinyglobby3.glob)("**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}", {
|
|
2127
|
+
cwd: root,
|
|
2128
|
+
absolute: true,
|
|
2129
|
+
onlyFiles: true,
|
|
2130
|
+
ignore: ["**/node_modules/**", "**/.git/**", outRel ? `${outRel}/**` : ".giri/**"]
|
|
2131
|
+
});
|
|
1965
2132
|
const importers = /* @__PURE__ */ new Map();
|
|
1966
2133
|
const nodes = /* @__PURE__ */ new Set();
|
|
1967
|
-
for (const
|
|
1968
|
-
if (
|
|
1969
|
-
continue;
|
|
1970
|
-
}
|
|
1971
|
-
const mod = require.cache[id];
|
|
1972
|
-
if (!mod) {
|
|
2134
|
+
for (const file of files) {
|
|
2135
|
+
if (file.startsWith(outDir)) {
|
|
1973
2136
|
continue;
|
|
1974
2137
|
}
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
if (!
|
|
2138
|
+
for (const specifier of importSpecifiers(file)) {
|
|
2139
|
+
const dep = resolveSpecifier(specifier, file, config.alias, root);
|
|
2140
|
+
if (!dep || dep.startsWith(outDir)) {
|
|
1978
2141
|
continue;
|
|
1979
2142
|
}
|
|
1980
|
-
|
|
1981
|
-
const
|
|
1982
|
-
|
|
2143
|
+
const from = toSlash(file);
|
|
2144
|
+
const to = toSlash(dep);
|
|
2145
|
+
nodes.add(from);
|
|
2146
|
+
nodes.add(to);
|
|
2147
|
+
let set = importers.get(to);
|
|
1983
2148
|
if (!set) {
|
|
1984
2149
|
set = /* @__PURE__ */ new Set();
|
|
1985
|
-
importers.set(
|
|
2150
|
+
importers.set(to, set);
|
|
1986
2151
|
}
|
|
1987
|
-
set.add(
|
|
2152
|
+
set.add(from);
|
|
1988
2153
|
}
|
|
1989
2154
|
}
|
|
1990
2155
|
return { importers, nodes };
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
// src/loader/module-loader.ts
|
|
2159
|
+
var import_node_path14 = require("path");
|
|
2160
|
+
var toSlash2 = (path) => path.split(import_node_path14.sep).join("/");
|
|
2161
|
+
var isProjectModule = (id, root) => {
|
|
2162
|
+
return id.startsWith(root) && !id.includes(`${import_node_path14.sep}node_modules${import_node_path14.sep}`) && !id.includes(`${import_node_path14.sep}.giri${import_node_path14.sep}`);
|
|
1991
2163
|
};
|
|
1992
2164
|
var collectDependents = (graph, start) => {
|
|
1993
2165
|
const out = /* @__PURE__ */ new Set([start]);
|
|
@@ -2005,13 +2177,13 @@ var collectDependents = (graph, start) => {
|
|
|
2005
2177
|
};
|
|
2006
2178
|
var purgeModules = (files) => {
|
|
2007
2179
|
for (const id of Object.keys(require.cache)) {
|
|
2008
|
-
if (files.has(
|
|
2180
|
+
if (files.has(toSlash2(id))) {
|
|
2009
2181
|
delete require.cache[id];
|
|
2010
2182
|
}
|
|
2011
2183
|
}
|
|
2012
2184
|
};
|
|
2013
2185
|
var purgeProjectModules = (cwd) => {
|
|
2014
|
-
const root = (0,
|
|
2186
|
+
const root = (0, import_node_path14.resolve)(cwd) + import_node_path14.sep;
|
|
2015
2187
|
for (const id of Object.keys(require.cache)) {
|
|
2016
2188
|
if (isProjectModule(id, root)) {
|
|
2017
2189
|
delete require.cache[id];
|
|
@@ -2019,9 +2191,9 @@ var purgeProjectModules = (cwd) => {
|
|
|
2019
2191
|
}
|
|
2020
2192
|
};
|
|
2021
2193
|
var purgeGeneratedModules = (outDir) => {
|
|
2022
|
-
const root = (0,
|
|
2194
|
+
const root = (0, import_node_path14.resolve)(outDir) + import_node_path14.sep;
|
|
2023
2195
|
for (const id of Object.keys(require.cache)) {
|
|
2024
|
-
if ((0,
|
|
2196
|
+
if ((0, import_node_path14.resolve)(id).startsWith(root)) {
|
|
2025
2197
|
delete require.cache[id];
|
|
2026
2198
|
}
|
|
2027
2199
|
}
|
|
@@ -2048,8 +2220,8 @@ function createWatchUpdater(config, initial) {
|
|
|
2048
2220
|
const key = route.file;
|
|
2049
2221
|
try {
|
|
2050
2222
|
const { createSchemaProgram: createSchemaProgram2, extractRouteResponses: extractRouteResponses2 } = await Promise.resolve().then(() => (init_schema(), schema_exports));
|
|
2051
|
-
const appTypes = (0,
|
|
2052
|
-
const program = createSchemaProgram2(paths, (0,
|
|
2223
|
+
const appTypes = (0, import_node_path15.join)(paths.outDir, "types", "app.d.ts");
|
|
2224
|
+
const program = createSchemaProgram2(paths, (0, import_node_fs10.existsSync)(appTypes) ? [key, appTypes] : [key]);
|
|
2053
2225
|
data.responsesByFile.set(key, extractRouteResponses2(program, key));
|
|
2054
2226
|
} catch {
|
|
2055
2227
|
}
|
|
@@ -2080,15 +2252,15 @@ function createWatchUpdater(config, initial) {
|
|
|
2080
2252
|
if (!filename) {
|
|
2081
2253
|
return fullResync();
|
|
2082
2254
|
}
|
|
2083
|
-
const abs = (0,
|
|
2255
|
+
const abs = (0, import_node_path15.resolve)((0, import_node_path15.dirname)(paths.routesDir), filename);
|
|
2084
2256
|
const file = slash(abs);
|
|
2085
|
-
if (!(0,
|
|
2257
|
+
if (!(0, import_node_fs10.existsSync)(abs)) {
|
|
2086
2258
|
return fullResync();
|
|
2087
2259
|
}
|
|
2088
|
-
if ((0,
|
|
2260
|
+
if ((0, import_node_fs10.statSync)(abs).isDirectory()) {
|
|
2089
2261
|
return "skip";
|
|
2090
2262
|
}
|
|
2091
|
-
const graph =
|
|
2263
|
+
const graph = await buildImportGraph(config, paths.cwd);
|
|
2092
2264
|
const isRoute = routes.some((candidate) => slash(candidate.file) === file);
|
|
2093
2265
|
if (!graph.nodes.has(file) && !isRoute) {
|
|
2094
2266
|
return fullResync();
|
|
@@ -2103,6 +2275,7 @@ function createWatchUpdater(config, initial) {
|
|
|
2103
2275
|
}
|
|
2104
2276
|
await writeManifest(paths, routes, data);
|
|
2105
2277
|
await writeOpenApi(paths, routes, data);
|
|
2278
|
+
await writeSyncCache(paths, await syncFingerprint(config, paths), data);
|
|
2106
2279
|
purgeGeneratedModules(paths.outDir);
|
|
2107
2280
|
return "incremental";
|
|
2108
2281
|
}
|
|
@@ -2110,20 +2283,20 @@ function createWatchUpdater(config, initial) {
|
|
|
2110
2283
|
}
|
|
2111
2284
|
|
|
2112
2285
|
// src/lifecycle.ts
|
|
2113
|
-
var
|
|
2114
|
-
var
|
|
2286
|
+
var import_node_fs11 = require("fs");
|
|
2287
|
+
var import_node_path16 = require("path");
|
|
2115
2288
|
var MAIN_EXTENSIONS2 = ["ts", "tsx", "mts", "cts", "js", "jsx", "mjs", "cjs"];
|
|
2116
2289
|
function resolveMainFile(cwd) {
|
|
2117
2290
|
for (const ext of MAIN_EXTENSIONS2) {
|
|
2118
|
-
const file = (0,
|
|
2119
|
-
if ((0,
|
|
2291
|
+
const file = (0, import_node_path16.join)(cwd, "src", `main.${ext}`);
|
|
2292
|
+
if ((0, import_node_fs11.existsSync)(file)) {
|
|
2120
2293
|
return file;
|
|
2121
2294
|
}
|
|
2122
2295
|
}
|
|
2123
2296
|
return void 0;
|
|
2124
2297
|
}
|
|
2125
2298
|
async function loadLifecycle(cwd = process.cwd()) {
|
|
2126
|
-
const file = resolveMainFile((0,
|
|
2299
|
+
const file = resolveMainFile((0, import_node_path16.resolve)(cwd));
|
|
2127
2300
|
if (!file) {
|
|
2128
2301
|
return {};
|
|
2129
2302
|
}
|
|
@@ -2281,25 +2454,25 @@ function parseFlags(args) {
|
|
|
2281
2454
|
return flags;
|
|
2282
2455
|
}
|
|
2283
2456
|
async function ensureGitignore(cwd) {
|
|
2284
|
-
const file = (0,
|
|
2457
|
+
const file = (0, import_node_path17.join)(cwd, ".gitignore");
|
|
2285
2458
|
const entry = ".giri";
|
|
2286
|
-
if (!(0,
|
|
2287
|
-
await (0,
|
|
2459
|
+
if (!(0, import_node_fs12.existsSync)(file)) {
|
|
2460
|
+
await (0, import_promises5.writeFile)(file, `${entry}
|
|
2288
2461
|
`);
|
|
2289
2462
|
return;
|
|
2290
2463
|
}
|
|
2291
|
-
const content = await (0,
|
|
2464
|
+
const content = await (0, import_promises5.readFile)(file, "utf8");
|
|
2292
2465
|
if (!content.split(/\r?\n/).includes(entry)) {
|
|
2293
|
-
await (0,
|
|
2466
|
+
await (0, import_promises5.appendFile)(file, `${content.endsWith("\n") ? "" : "\n"}${entry}
|
|
2294
2467
|
`);
|
|
2295
2468
|
}
|
|
2296
2469
|
}
|
|
2297
2470
|
async function ensureTsConfig(cwd) {
|
|
2298
|
-
const file = (0,
|
|
2299
|
-
if ((0,
|
|
2471
|
+
const file = (0, import_node_path17.join)(cwd, "tsconfig.json");
|
|
2472
|
+
if ((0, import_node_fs12.existsSync)(file)) {
|
|
2300
2473
|
return;
|
|
2301
2474
|
}
|
|
2302
|
-
await (0,
|
|
2475
|
+
await (0, import_promises5.writeFile)(
|
|
2303
2476
|
file,
|
|
2304
2477
|
`${JSON.stringify(
|
|
2305
2478
|
{
|
|
@@ -2325,7 +2498,7 @@ async function ensureTsConfig(cwd) {
|
|
|
2325
2498
|
async function missingDeps(cwd, candidates) {
|
|
2326
2499
|
let pkg = {};
|
|
2327
2500
|
try {
|
|
2328
|
-
pkg = JSON.parse(await (0,
|
|
2501
|
+
pkg = JSON.parse(await (0, import_promises5.readFile)((0, import_node_path17.join)(cwd, "package.json"), "utf8"));
|
|
2329
2502
|
} catch {
|
|
2330
2503
|
}
|
|
2331
2504
|
const present = /* @__PURE__ */ new Set();
|
|
@@ -2394,7 +2567,7 @@ async function selectAdapter(interactive) {
|
|
|
2394
2567
|
return ADAPTERS.find((adapter) => adapter.value === picked) ?? null;
|
|
2395
2568
|
}
|
|
2396
2569
|
async function initProject(cwd, flags) {
|
|
2397
|
-
if (!(0,
|
|
2570
|
+
if (!(0, import_node_fs12.existsSync)((0, import_node_path17.join)(cwd, "package.json"))) {
|
|
2398
2571
|
throw new Error(
|
|
2399
2572
|
"No package.json found. Run `giri init` inside an existing project - set one up first (e.g. `npm init -y` and install typescript), then re-run."
|
|
2400
2573
|
);
|
|
@@ -2419,14 +2592,14 @@ async function initProject(cwd, flags) {
|
|
|
2419
2592
|
prompts.cancel(`The ${adapter.label} adapter isn't available yet - only Hono ships today.`);
|
|
2420
2593
|
return;
|
|
2421
2594
|
}
|
|
2422
|
-
const configPath = (0,
|
|
2423
|
-
if (!(0,
|
|
2424
|
-
await (0,
|
|
2595
|
+
const configPath = (0, import_node_path17.join)(cwd, "giri.config.ts");
|
|
2596
|
+
if (!(0, import_node_fs12.existsSync)(configPath)) {
|
|
2597
|
+
await (0, import_promises5.writeFile)(configPath, configSource(adapter));
|
|
2425
2598
|
}
|
|
2426
|
-
const routePath = (0,
|
|
2427
|
-
if (!(0,
|
|
2428
|
-
await (0,
|
|
2429
|
-
await (0,
|
|
2599
|
+
const routePath = (0, import_node_path17.join)(cwd, "src", "routes", "+get.ts");
|
|
2600
|
+
if (!(0, import_node_fs12.existsSync)(routePath)) {
|
|
2601
|
+
await (0, import_promises5.mkdir)((0, import_node_path17.join)(cwd, "src", "routes"), { recursive: true });
|
|
2602
|
+
await (0, import_promises5.writeFile)(
|
|
2430
2603
|
routePath,
|
|
2431
2604
|
[
|
|
2432
2605
|
'import type { Handle } from "@boon4681/giri";',
|
|
@@ -2497,21 +2670,30 @@ async function serveProject(config, flags) {
|
|
|
2497
2670
|
const { watch } = await import("chokidar");
|
|
2498
2671
|
let stop;
|
|
2499
2672
|
const boot = async (cfg) => {
|
|
2500
|
-
const initial = await syncProject(cfg);
|
|
2501
|
-
log2.success(
|
|
2502
|
-
`synced ${initial.routes.length} route${initial.routes.length === 1 ? "" : "s"} ${muted(`at ${initial.paths.outDir}`)}`,
|
|
2503
|
-
"sync"
|
|
2504
|
-
);
|
|
2505
2673
|
const closers = [];
|
|
2506
|
-
closers.push(registerAliasResolver(cfg.alias,
|
|
2674
|
+
closers.push(registerAliasResolver(cfg.alias, (0, import_node_path17.resolve)(process.cwd())));
|
|
2507
2675
|
const lifecycle = await loadLifecycle();
|
|
2508
|
-
const
|
|
2509
|
-
|
|
2676
|
+
const sync = syncProject(cfg).then((initial2) => {
|
|
2677
|
+
log2.success(
|
|
2678
|
+
`synced ${initial2.routes.length} route${initial2.routes.length === 1 ? "" : "s"} ${muted(`at ${initial2.paths.outDir}`)}`,
|
|
2679
|
+
"sync"
|
|
2680
|
+
);
|
|
2681
|
+
return initial2;
|
|
2682
|
+
});
|
|
2683
|
+
const [initial, services] = await Promise.all([sync, runInit(lifecycle)]);
|
|
2684
|
+
const loader = await safeRegister();
|
|
2685
|
+
closers.push(loader.unregister);
|
|
2686
|
+
let current = await buildGiriApp(cfg, {
|
|
2687
|
+
services,
|
|
2688
|
+
lazy: true,
|
|
2689
|
+
loaderRegistered: true,
|
|
2690
|
+
aliasResolverRegistered: true
|
|
2691
|
+
});
|
|
2510
2692
|
const port = flags.port ?? cfg.server?.port ?? 3e3;
|
|
2511
2693
|
const hostname = flags.hostname ?? cfg.server?.hostname;
|
|
2512
2694
|
if (flags.watch) {
|
|
2513
|
-
const srcDir = (0,
|
|
2514
|
-
if ((0,
|
|
2695
|
+
const srcDir = (0, import_node_path17.resolve)(current.paths.routesDir, "..");
|
|
2696
|
+
if ((0, import_node_fs12.existsSync)(srcDir)) {
|
|
2515
2697
|
let timer;
|
|
2516
2698
|
let syncing = false;
|
|
2517
2699
|
const changed = /* @__PURE__ */ new Set();
|
|
@@ -2541,7 +2723,7 @@ async function serveProject(config, flags) {
|
|
|
2541
2723
|
}
|
|
2542
2724
|
rebuild = true;
|
|
2543
2725
|
if (name) {
|
|
2544
|
-
dirtySet.add((0,
|
|
2726
|
+
dirtySet.add((0, import_node_path17.resolve)(srcDir, name));
|
|
2545
2727
|
}
|
|
2546
2728
|
const rel = name ? `src/${name.replace(/\\/g, "/")}` : "src";
|
|
2547
2729
|
log2.change(outcome === "full" ? "sync" : "update", rel, bump(rel));
|
|
@@ -2553,7 +2735,10 @@ async function serveProject(config, flags) {
|
|
|
2553
2735
|
if (rebuild) {
|
|
2554
2736
|
current = await buildGiriApp(cfg, {
|
|
2555
2737
|
services,
|
|
2556
|
-
dirty: fullSync ? void 0 : dirtySet
|
|
2738
|
+
dirty: fullSync ? void 0 : dirtySet,
|
|
2739
|
+
lazy: true,
|
|
2740
|
+
loaderRegistered: true,
|
|
2741
|
+
aliasResolverRegistered: true
|
|
2557
2742
|
});
|
|
2558
2743
|
}
|
|
2559
2744
|
}
|
|
@@ -2566,9 +2751,9 @@ async function serveProject(config, flags) {
|
|
|
2566
2751
|
void flush();
|
|
2567
2752
|
}
|
|
2568
2753
|
};
|
|
2569
|
-
const watcher = watch(srcDir, { persistent: true });
|
|
2754
|
+
const watcher = watch(srcDir, { persistent: true, ignoreInitial: true });
|
|
2570
2755
|
const onFileChange = (filename) => {
|
|
2571
|
-
changed.add(filename);
|
|
2756
|
+
changed.add((0, import_node_path17.isAbsolute)(filename) ? (0, import_node_path17.relative)(srcDir, filename) : filename);
|
|
2572
2757
|
clearTimeout(timer);
|
|
2573
2758
|
timer = setTimeout(() => void flush(), 150);
|
|
2574
2759
|
};
|
|
@@ -2599,11 +2784,11 @@ async function serveProject(config, flags) {
|
|
|
2599
2784
|
};
|
|
2600
2785
|
};
|
|
2601
2786
|
await boot(config);
|
|
2602
|
-
const configPath = flags.watch ? findConfigPath((0,
|
|
2787
|
+
const configPath = flags.watch ? findConfigPath((0, import_node_path17.resolve)(process.cwd())) : void 0;
|
|
2603
2788
|
if (configPath) {
|
|
2604
2789
|
let timer;
|
|
2605
2790
|
let restarting = false;
|
|
2606
|
-
const configName = (0,
|
|
2791
|
+
const configName = (0, import_node_path17.basename)(configPath);
|
|
2607
2792
|
const restart = async () => {
|
|
2608
2793
|
if (restarting) {
|
|
2609
2794
|
return;
|
|
@@ -2622,12 +2807,10 @@ async function serveProject(config, flags) {
|
|
|
2622
2807
|
restarting = false;
|
|
2623
2808
|
}
|
|
2624
2809
|
};
|
|
2625
|
-
const configWatcher = watch(
|
|
2626
|
-
configWatcher.on("all", (
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
timer = setTimeout(() => void restart(), 150);
|
|
2630
|
-
}
|
|
2810
|
+
const configWatcher = watch(configPath, { persistent: true, ignoreInitial: true });
|
|
2811
|
+
configWatcher.on("all", () => {
|
|
2812
|
+
clearTimeout(timer);
|
|
2813
|
+
timer = setTimeout(() => void restart(), 150);
|
|
2631
2814
|
});
|
|
2632
2815
|
}
|
|
2633
2816
|
registerShutdown(() => stop?.());
|
|
@@ -2653,7 +2836,7 @@ function registerShutdown(cleanup) {
|
|
|
2653
2836
|
}
|
|
2654
2837
|
async function main() {
|
|
2655
2838
|
const [command = "help", ...args] = process.argv.slice(2);
|
|
2656
|
-
const cwd = (0,
|
|
2839
|
+
const cwd = (0, import_node_path17.resolve)(process.cwd());
|
|
2657
2840
|
if (command === "help" || command === "--help" || command === "-h") {
|
|
2658
2841
|
help();
|
|
2659
2842
|
return;
|