clivly 0.10.0 → 0.10.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/core-entity-heuristics.cjs +1 -0
- package/core-entity-heuristics.d.cts +2 -2
- package/core-entity-heuristics.d.mts +2 -2
- package/core-entity-heuristics.mjs +2 -2
- package/index.cjs +45 -6
- package/index.mjs +46 -7
- package/internal-entity-heuristics.cjs +1 -0
- package/internal-entity-heuristics.d.cts +2 -1
- package/internal-entity-heuristics.d.mts +2 -1
- package/internal-entity-heuristics.mjs +1 -1
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ const require_internal_entity_heuristics = require("./internal-entity-heuristics
|
|
|
4
4
|
require("./deprecate-subpath-B9ngvizt.cjs").warnDeprecatedSubpath("clivly/core/entity-heuristics", "clivly/internal/entity-heuristics");
|
|
5
5
|
//#endregion
|
|
6
6
|
exports.TARGET_CONCEPTS = require_internal_entity_heuristics.TARGET_CONCEPTS;
|
|
7
|
+
exports.hasDefiningColumn = require_internal_entity_heuristics.hasDefiningColumn;
|
|
7
8
|
exports.hasSensitiveColumns = require_internal_entity_heuristics.hasSensitiveColumns;
|
|
8
9
|
exports.matchesConcept = require_internal_entity_heuristics.matchesConcept;
|
|
9
10
|
exports.requiredFieldsFor = require_internal_entity_heuristics.requiredFieldsFor;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { p as DiscoveredColumnMeta } from "./entity-config-DNQAMbMS.cjs";
|
|
2
|
-
import { FieldSuggestion, RelationshipSuggestion, ScoredTable, SuggestedVia, TARGET_CONCEPTS, TargetConcept, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping } from "./internal-entity-heuristics.cjs";
|
|
3
|
-
export { type DiscoveredColumnMeta, FieldSuggestion, RelationshipSuggestion, ScoredTable, SuggestedVia, TARGET_CONCEPTS, TargetConcept, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping };
|
|
2
|
+
import { FieldSuggestion, RelationshipSuggestion, ScoredTable, SuggestedVia, TARGET_CONCEPTS, TargetConcept, hasDefiningColumn, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping } from "./internal-entity-heuristics.cjs";
|
|
3
|
+
export { type DiscoveredColumnMeta, FieldSuggestion, RelationshipSuggestion, ScoredTable, SuggestedVia, TARGET_CONCEPTS, TargetConcept, hasDefiningColumn, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { p as DiscoveredColumnMeta } from "./entity-config-DNQAMbMS.mjs";
|
|
2
|
-
import { FieldSuggestion, RelationshipSuggestion, ScoredTable, SuggestedVia, TARGET_CONCEPTS, TargetConcept, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping } from "./internal-entity-heuristics.mjs";
|
|
3
|
-
export { type DiscoveredColumnMeta, FieldSuggestion, RelationshipSuggestion, ScoredTable, SuggestedVia, TARGET_CONCEPTS, TargetConcept, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping };
|
|
2
|
+
import { FieldSuggestion, RelationshipSuggestion, ScoredTable, SuggestedVia, TARGET_CONCEPTS, TargetConcept, hasDefiningColumn, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping } from "./internal-entity-heuristics.mjs";
|
|
3
|
+
export { type DiscoveredColumnMeta, FieldSuggestion, RelationshipSuggestion, ScoredTable, SuggestedVia, TARGET_CONCEPTS, TargetConcept, hasDefiningColumn, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { TARGET_CONCEPTS, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping } from "./internal-entity-heuristics.mjs";
|
|
1
|
+
import { TARGET_CONCEPTS, hasDefiningColumn, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping } from "./internal-entity-heuristics.mjs";
|
|
2
2
|
import { t as warnDeprecatedSubpath } from "./deprecate-subpath-CmvZtCpE.mjs";
|
|
3
3
|
//#region src/core-entity-heuristics.ts
|
|
4
4
|
warnDeprecatedSubpath("clivly/core/entity-heuristics", "clivly/internal/entity-heuristics");
|
|
5
5
|
//#endregion
|
|
6
|
-
export { TARGET_CONCEPTS, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping };
|
|
6
|
+
export { TARGET_CONCEPTS, hasDefiningColumn, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping };
|
package/index.cjs
CHANGED
|
@@ -1501,11 +1501,17 @@ function toScoredTable(table) {
|
|
|
1501
1501
|
}))
|
|
1502
1502
|
};
|
|
1503
1503
|
}
|
|
1504
|
+
function columnNames(table) {
|
|
1505
|
+
return table.columns.map((column) => column.dbName);
|
|
1506
|
+
}
|
|
1504
1507
|
function rankCandidates$1(tables, concept) {
|
|
1505
1508
|
return tables.map((t) => ({
|
|
1506
1509
|
t,
|
|
1507
1510
|
m: require_internal_entity_heuristics.matchesConcept(t.tableName, concept)
|
|
1508
|
-
})).filter((c) => Boolean(c.m)).sort((a, b) =>
|
|
1511
|
+
})).filter((c) => Boolean(c.m)).sort((a, b) => {
|
|
1512
|
+
const usable = Number(require_internal_entity_heuristics.hasDefiningColumn(concept, columnNames(b.t))) - Number(require_internal_entity_heuristics.hasDefiningColumn(concept, columnNames(a.t)));
|
|
1513
|
+
return usable === 0 ? Number(b.m.exact) - Number(a.m.exact) : usable;
|
|
1514
|
+
}).map((c) => c.t);
|
|
1509
1515
|
}
|
|
1510
1516
|
function selectEntities(tables) {
|
|
1511
1517
|
const contactCands = rankCandidates$1(tables, "contact");
|
|
@@ -1768,7 +1774,8 @@ export default defineNitroPlugin(() => {
|
|
|
1768
1774
|
`;
|
|
1769
1775
|
}
|
|
1770
1776
|
function sveltekitHook(importPath) {
|
|
1771
|
-
return `import
|
|
1777
|
+
return `import "dotenv/config";
|
|
1778
|
+
import clivly from "${importPath}";
|
|
1772
1779
|
|
|
1773
1780
|
// Clivly boot hook. This module is evaluated once when the server starts.
|
|
1774
1781
|
// ${FAILURE_NOTE}
|
|
@@ -2133,7 +2140,25 @@ function routePath(framework, kind, layout = "app") {
|
|
|
2133
2140
|
}
|
|
2134
2141
|
const WINDOWS_SEP = /\\/g;
|
|
2135
2142
|
const LEADING_DOT_SLASH = /^\.\//;
|
|
2143
|
+
const ALIAS_MARKER = /^[$~#]/;
|
|
2144
|
+
const SCOPED_PACKAGE = /^@[^/]+\/[^/]+/;
|
|
2145
|
+
const PROJECT_ROOT_DIRS = /* @__PURE__ */ new Set([
|
|
2146
|
+
"app",
|
|
2147
|
+
"lib",
|
|
2148
|
+
"server",
|
|
2149
|
+
"src",
|
|
2150
|
+
"source",
|
|
2151
|
+
"utils"
|
|
2152
|
+
]);
|
|
2153
|
+
function isAlreadyResolvable(specifier) {
|
|
2154
|
+
if (specifier.startsWith(".") || specifier.startsWith("/")) return false;
|
|
2155
|
+
if (ALIAS_MARKER.test(specifier) || SCOPED_PACKAGE.test(specifier)) return true;
|
|
2156
|
+
if (specifier.startsWith("@")) return true;
|
|
2157
|
+
const [head] = specifier.split("/");
|
|
2158
|
+
return !(head && PROJECT_ROOT_DIRS.has(head));
|
|
2159
|
+
}
|
|
2136
2160
|
function hostImportPath(routeFilePath, appRelative, paths) {
|
|
2161
|
+
if (isAlreadyResolvable(appRelative)) return appRelative;
|
|
2137
2162
|
const fromRoot = appRelative.replace(LEADING_DOT_SLASH, "");
|
|
2138
2163
|
const alias = aliasFor({
|
|
2139
2164
|
paths,
|
|
@@ -2452,7 +2477,12 @@ const AUTH_MODULE_PATHS = [
|
|
|
2452
2477
|
"src/lib/auth",
|
|
2453
2478
|
"app/lib/auth",
|
|
2454
2479
|
"server/auth",
|
|
2455
|
-
"src/server/auth"
|
|
2480
|
+
"src/server/auth",
|
|
2481
|
+
"src/lib/server/auth",
|
|
2482
|
+
"lib/server/auth",
|
|
2483
|
+
"server/utils/auth",
|
|
2484
|
+
"src/lib/auth/index",
|
|
2485
|
+
"lib/auth/index"
|
|
2456
2486
|
];
|
|
2457
2487
|
/** A better-auth instance, duck-typed by the surface the adapter calls. */
|
|
2458
2488
|
function isBetterAuthInstance(value) {
|
|
@@ -3640,6 +3670,7 @@ async function acquireSchema(options, deps) {
|
|
|
3640
3670
|
out(` ORM: ${orm}\n`);
|
|
3641
3671
|
out(` Auth: ${auth}${deps.authWiring.complete ? " (wired)" : ""}\n`);
|
|
3642
3672
|
if (framework === "nextjs") out(` Layout: ${layout}\n`);
|
|
3673
|
+
if (auth === "better-auth" && !deps.authWiring.complete) out("\n ⚠️ Could not locate your better-auth instance.\n The verify route will import a placeholder path that does not\n resolve. Point it at the real module with:\n\n clivly init --force --auth-import <specifier>\n\n Accepts an alias ($lib/server/auth, @/lib/auth), a package name,\n or a project-relative path (src/lib/server/auth).\n");
|
|
3643
3674
|
out("\n");
|
|
3644
3675
|
if (orm !== "drizzle") {
|
|
3645
3676
|
out(`clivly init currently generates config for Drizzle only. Detected ORM: ${orm}\n`);
|
|
@@ -3647,6 +3678,7 @@ async function acquireSchema(options, deps) {
|
|
|
3647
3678
|
}
|
|
3648
3679
|
if (framework === "unknown") {
|
|
3649
3680
|
out("clivly init doesn't recognise your framework yet (looked for Next.js, TanStack Start, SvelteKit, Remix, Nuxt). Route file generation needs one of these.\n");
|
|
3681
|
+
if ("vue" in appDeps) out("\nUsing Vue? Clivly supports Vue through Nuxt. A Vite SPA has no server\nto mount the sync route on, so the route files need Nuxt's server\ndirectory (or any of the frameworks above).\n");
|
|
3650
3682
|
return { code: 1 };
|
|
3651
3683
|
}
|
|
3652
3684
|
const schemaPath = deps.resolvePath(options.cwd);
|
|
@@ -3745,13 +3777,19 @@ function previewMutations(deps, mutations, options) {
|
|
|
3745
3777
|
}
|
|
3746
3778
|
out(options.diff ? "\nRe-run without --diff to apply; --force to overwrite the files marked conflict.\n" : "\nRe-run without --dry-run to apply.\n");
|
|
3747
3779
|
}
|
|
3748
|
-
function printNextSteps(out, authComplete, loginRan, envFile) {
|
|
3780
|
+
function printNextSteps(out, authComplete, loginRan, envFile, needsViteDotenv = false) {
|
|
3749
3781
|
out("\nNext steps:\n");
|
|
3750
3782
|
out(loginRan ? " 1. Credentials written by `clivly login`\n" : ` 1. Add CLIVLY_SECRET_KEY to ${envFile} — create one at\n ${CREDENTIALS_LOCATION}\n (the legacy CLIVLY_API_KEY is still accepted)\n`);
|
|
3751
3783
|
out(" 2. Local dev: run `clivly dev` for dashboard-triggered sync\n");
|
|
3752
3784
|
out(" It tunnels your app and registers the URL for you — remote sync is\n deploy-only otherwise, so nothing is broken if you skip it. Once deployed\n to Vercel/Cloudflare/Railway/Render/Fly the URL is detected automatically;\n set CLIVLY_SYNC_TRIGGER_URL by hand only for a custom domain.\n");
|
|
3753
|
-
|
|
3785
|
+
let step = authComplete ? 3 : 4;
|
|
3754
3786
|
if (!authComplete) out(" 3. Finish resolveUser in the auth/verify route\n");
|
|
3787
|
+
if (needsViteDotenv) {
|
|
3788
|
+
out(` ${step}. Add \`import "dotenv/config";\` to vite.config.ts\n SvelteKit populates \$env/*, not process.env, which better-auth and
|
|
3789
|
+
clivly.config both read — without it \`vite build\` fails.
|
|
3790
|
+
`);
|
|
3791
|
+
step += 1;
|
|
3792
|
+
}
|
|
3755
3793
|
out(` ${step}. Run \`clivly status\` to see where you are\n`);
|
|
3756
3794
|
out("\nAfter editing clivly.config.ts, restart your app — it loads the config\nat boot, so a running server keeps using the old one.\n");
|
|
3757
3795
|
}
|
|
@@ -3807,7 +3845,8 @@ async function scaffold(options, deps, plan) {
|
|
|
3807
3845
|
out(" Run `clivly login` from a terminal to write CLIVLY_SECRET_KEY and CLIVLY_SYNC_TRIGGER_SECRET.\n");
|
|
3808
3846
|
} else loginRan = await deps.login(options.cwd) === 0;
|
|
3809
3847
|
}
|
|
3810
|
-
|
|
3848
|
+
const initFramework = detectFramework(deps.readDepsFn(options.cwd));
|
|
3849
|
+
printNextSteps(out, deps.authWiring.complete, loginRan, envFileFor(initFramework), initFramework === "sveltekit" && deps.authWiring.hostImport !== null);
|
|
3811
3850
|
return 0;
|
|
3812
3851
|
}
|
|
3813
3852
|
function normalizeAppRoot(options) {
|
package/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as CANONICAL_FIELDS } from "./entity-config-C4d3K9CP.mjs";
|
|
3
3
|
import "./mapping-score-C68uAqGB.mjs";
|
|
4
|
-
import { matchesConcept, requiredFieldsFor, scoreFieldMap, scoreRelationships, suggestCursorField, toFieldMap } from "./internal-entity-heuristics.mjs";
|
|
4
|
+
import { hasDefiningColumn, matchesConcept, requiredFieldsFor, scoreFieldMap, scoreRelationships, suggestCursorField, toFieldMap } from "./internal-entity-heuristics.mjs";
|
|
5
5
|
import { s as isPlaceholderUrl, t as createClivlySDK } from "./sdk-D6gX0TXS.mjs";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
7
|
import { spawn } from "node:child_process";
|
|
@@ -1500,11 +1500,17 @@ function toScoredTable(table) {
|
|
|
1500
1500
|
}))
|
|
1501
1501
|
};
|
|
1502
1502
|
}
|
|
1503
|
+
function columnNames(table) {
|
|
1504
|
+
return table.columns.map((column) => column.dbName);
|
|
1505
|
+
}
|
|
1503
1506
|
function rankCandidates$1(tables, concept) {
|
|
1504
1507
|
return tables.map((t) => ({
|
|
1505
1508
|
t,
|
|
1506
1509
|
m: matchesConcept(t.tableName, concept)
|
|
1507
|
-
})).filter((c) => Boolean(c.m)).sort((a, b) =>
|
|
1510
|
+
})).filter((c) => Boolean(c.m)).sort((a, b) => {
|
|
1511
|
+
const usable = Number(hasDefiningColumn(concept, columnNames(b.t))) - Number(hasDefiningColumn(concept, columnNames(a.t)));
|
|
1512
|
+
return usable === 0 ? Number(b.m.exact) - Number(a.m.exact) : usable;
|
|
1513
|
+
}).map((c) => c.t);
|
|
1508
1514
|
}
|
|
1509
1515
|
function selectEntities(tables) {
|
|
1510
1516
|
const contactCands = rankCandidates$1(tables, "contact");
|
|
@@ -1767,7 +1773,8 @@ export default defineNitroPlugin(() => {
|
|
|
1767
1773
|
`;
|
|
1768
1774
|
}
|
|
1769
1775
|
function sveltekitHook(importPath) {
|
|
1770
|
-
return `import
|
|
1776
|
+
return `import "dotenv/config";
|
|
1777
|
+
import clivly from "${importPath}";
|
|
1771
1778
|
|
|
1772
1779
|
// Clivly boot hook. This module is evaluated once when the server starts.
|
|
1773
1780
|
// ${FAILURE_NOTE}
|
|
@@ -2132,7 +2139,25 @@ function routePath(framework, kind, layout = "app") {
|
|
|
2132
2139
|
}
|
|
2133
2140
|
const WINDOWS_SEP = /\\/g;
|
|
2134
2141
|
const LEADING_DOT_SLASH = /^\.\//;
|
|
2142
|
+
const ALIAS_MARKER = /^[$~#]/;
|
|
2143
|
+
const SCOPED_PACKAGE = /^@[^/]+\/[^/]+/;
|
|
2144
|
+
const PROJECT_ROOT_DIRS = /* @__PURE__ */ new Set([
|
|
2145
|
+
"app",
|
|
2146
|
+
"lib",
|
|
2147
|
+
"server",
|
|
2148
|
+
"src",
|
|
2149
|
+
"source",
|
|
2150
|
+
"utils"
|
|
2151
|
+
]);
|
|
2152
|
+
function isAlreadyResolvable(specifier) {
|
|
2153
|
+
if (specifier.startsWith(".") || specifier.startsWith("/")) return false;
|
|
2154
|
+
if (ALIAS_MARKER.test(specifier) || SCOPED_PACKAGE.test(specifier)) return true;
|
|
2155
|
+
if (specifier.startsWith("@")) return true;
|
|
2156
|
+
const [head] = specifier.split("/");
|
|
2157
|
+
return !(head && PROJECT_ROOT_DIRS.has(head));
|
|
2158
|
+
}
|
|
2135
2159
|
function hostImportPath(routeFilePath, appRelative, paths) {
|
|
2160
|
+
if (isAlreadyResolvable(appRelative)) return appRelative;
|
|
2136
2161
|
const fromRoot = appRelative.replace(LEADING_DOT_SLASH, "");
|
|
2137
2162
|
const alias = aliasFor({
|
|
2138
2163
|
paths,
|
|
@@ -2451,7 +2476,12 @@ const AUTH_MODULE_PATHS = [
|
|
|
2451
2476
|
"src/lib/auth",
|
|
2452
2477
|
"app/lib/auth",
|
|
2453
2478
|
"server/auth",
|
|
2454
|
-
"src/server/auth"
|
|
2479
|
+
"src/server/auth",
|
|
2480
|
+
"src/lib/server/auth",
|
|
2481
|
+
"lib/server/auth",
|
|
2482
|
+
"server/utils/auth",
|
|
2483
|
+
"src/lib/auth/index",
|
|
2484
|
+
"lib/auth/index"
|
|
2455
2485
|
];
|
|
2456
2486
|
/** A better-auth instance, duck-typed by the surface the adapter calls. */
|
|
2457
2487
|
function isBetterAuthInstance(value) {
|
|
@@ -3639,6 +3669,7 @@ async function acquireSchema(options, deps) {
|
|
|
3639
3669
|
out(` ORM: ${orm}\n`);
|
|
3640
3670
|
out(` Auth: ${auth}${deps.authWiring.complete ? " (wired)" : ""}\n`);
|
|
3641
3671
|
if (framework === "nextjs") out(` Layout: ${layout}\n`);
|
|
3672
|
+
if (auth === "better-auth" && !deps.authWiring.complete) out("\n ⚠️ Could not locate your better-auth instance.\n The verify route will import a placeholder path that does not\n resolve. Point it at the real module with:\n\n clivly init --force --auth-import <specifier>\n\n Accepts an alias ($lib/server/auth, @/lib/auth), a package name,\n or a project-relative path (src/lib/server/auth).\n");
|
|
3642
3673
|
out("\n");
|
|
3643
3674
|
if (orm !== "drizzle") {
|
|
3644
3675
|
out(`clivly init currently generates config for Drizzle only. Detected ORM: ${orm}\n`);
|
|
@@ -3646,6 +3677,7 @@ async function acquireSchema(options, deps) {
|
|
|
3646
3677
|
}
|
|
3647
3678
|
if (framework === "unknown") {
|
|
3648
3679
|
out("clivly init doesn't recognise your framework yet (looked for Next.js, TanStack Start, SvelteKit, Remix, Nuxt). Route file generation needs one of these.\n");
|
|
3680
|
+
if ("vue" in appDeps) out("\nUsing Vue? Clivly supports Vue through Nuxt. A Vite SPA has no server\nto mount the sync route on, so the route files need Nuxt's server\ndirectory (or any of the frameworks above).\n");
|
|
3649
3681
|
return { code: 1 };
|
|
3650
3682
|
}
|
|
3651
3683
|
const schemaPath = deps.resolvePath(options.cwd);
|
|
@@ -3744,13 +3776,19 @@ function previewMutations(deps, mutations, options) {
|
|
|
3744
3776
|
}
|
|
3745
3777
|
out(options.diff ? "\nRe-run without --diff to apply; --force to overwrite the files marked conflict.\n" : "\nRe-run without --dry-run to apply.\n");
|
|
3746
3778
|
}
|
|
3747
|
-
function printNextSteps(out, authComplete, loginRan, envFile) {
|
|
3779
|
+
function printNextSteps(out, authComplete, loginRan, envFile, needsViteDotenv = false) {
|
|
3748
3780
|
out("\nNext steps:\n");
|
|
3749
3781
|
out(loginRan ? " 1. Credentials written by `clivly login`\n" : ` 1. Add CLIVLY_SECRET_KEY to ${envFile} — create one at\n ${CREDENTIALS_LOCATION}\n (the legacy CLIVLY_API_KEY is still accepted)\n`);
|
|
3750
3782
|
out(" 2. Local dev: run `clivly dev` for dashboard-triggered sync\n");
|
|
3751
3783
|
out(" It tunnels your app and registers the URL for you — remote sync is\n deploy-only otherwise, so nothing is broken if you skip it. Once deployed\n to Vercel/Cloudflare/Railway/Render/Fly the URL is detected automatically;\n set CLIVLY_SYNC_TRIGGER_URL by hand only for a custom domain.\n");
|
|
3752
|
-
|
|
3784
|
+
let step = authComplete ? 3 : 4;
|
|
3753
3785
|
if (!authComplete) out(" 3. Finish resolveUser in the auth/verify route\n");
|
|
3786
|
+
if (needsViteDotenv) {
|
|
3787
|
+
out(` ${step}. Add \`import "dotenv/config";\` to vite.config.ts\n SvelteKit populates \$env/*, not process.env, which better-auth and
|
|
3788
|
+
clivly.config both read — without it \`vite build\` fails.
|
|
3789
|
+
`);
|
|
3790
|
+
step += 1;
|
|
3791
|
+
}
|
|
3754
3792
|
out(` ${step}. Run \`clivly status\` to see where you are\n`);
|
|
3755
3793
|
out("\nAfter editing clivly.config.ts, restart your app — it loads the config\nat boot, so a running server keeps using the old one.\n");
|
|
3756
3794
|
}
|
|
@@ -3806,7 +3844,8 @@ async function scaffold(options, deps, plan) {
|
|
|
3806
3844
|
out(" Run `clivly login` from a terminal to write CLIVLY_SECRET_KEY and CLIVLY_SYNC_TRIGGER_SECRET.\n");
|
|
3807
3845
|
} else loginRan = await deps.login(options.cwd) === 0;
|
|
3808
3846
|
}
|
|
3809
|
-
|
|
3847
|
+
const initFramework = detectFramework(deps.readDepsFn(options.cwd));
|
|
3848
|
+
printNextSteps(out, deps.authWiring.complete, loginRan, envFileFor(initFramework), initFramework === "sveltekit" && deps.authWiring.hostImport !== null);
|
|
3810
3849
|
return 0;
|
|
3811
3850
|
}
|
|
3812
3851
|
function normalizeAppRoot(options) {
|
|
@@ -495,6 +495,7 @@ function toFieldMap(scored) {
|
|
|
495
495
|
}
|
|
496
496
|
//#endregion
|
|
497
497
|
exports.TARGET_CONCEPTS = TARGET_CONCEPTS;
|
|
498
|
+
exports.hasDefiningColumn = hasDefiningColumn;
|
|
498
499
|
exports.hasSensitiveColumns = hasSensitiveColumns;
|
|
499
500
|
exports.matchesConcept = matchesConcept;
|
|
500
501
|
exports.requiredFieldsFor = requiredFieldsFor;
|
|
@@ -19,6 +19,7 @@ interface ScoredTable {
|
|
|
19
19
|
* They stay manually selectable — an explicit, informed choice is legitimate.
|
|
20
20
|
*/
|
|
21
21
|
declare function hasSensitiveColumns(columns: string[]): boolean;
|
|
22
|
+
declare function hasDefiningColumn(concept: TargetConcept, columns: string[]): boolean;
|
|
22
23
|
declare function scoreConcepts(table: ScoredTable): Scored<TargetConcept>[];
|
|
23
24
|
declare function topConcept(table: ScoredTable): {
|
|
24
25
|
best: Scored<TargetConcept>;
|
|
@@ -60,4 +61,4 @@ interface FieldSuggestion {
|
|
|
60
61
|
declare function scoreFieldMap(concept: TargetConcept, table: ScoredTable): Scored<FieldSuggestion>[];
|
|
61
62
|
declare function toFieldMap(scored: Scored<FieldSuggestion>[]): Record<string, string>;
|
|
62
63
|
//#endregion
|
|
63
|
-
export { type DiscoveredColumnMeta, FieldSuggestion, RelationshipSuggestion, ScoredTable, SuggestedVia, TARGET_CONCEPTS, TargetConcept, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping };
|
|
64
|
+
export { type DiscoveredColumnMeta, FieldSuggestion, RelationshipSuggestion, ScoredTable, SuggestedVia, TARGET_CONCEPTS, TargetConcept, hasDefiningColumn, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping };
|
|
@@ -19,6 +19,7 @@ interface ScoredTable {
|
|
|
19
19
|
* They stay manually selectable — an explicit, informed choice is legitimate.
|
|
20
20
|
*/
|
|
21
21
|
declare function hasSensitiveColumns(columns: string[]): boolean;
|
|
22
|
+
declare function hasDefiningColumn(concept: TargetConcept, columns: string[]): boolean;
|
|
22
23
|
declare function scoreConcepts(table: ScoredTable): Scored<TargetConcept>[];
|
|
23
24
|
declare function topConcept(table: ScoredTable): {
|
|
24
25
|
best: Scored<TargetConcept>;
|
|
@@ -60,4 +61,4 @@ interface FieldSuggestion {
|
|
|
60
61
|
declare function scoreFieldMap(concept: TargetConcept, table: ScoredTable): Scored<FieldSuggestion>[];
|
|
61
62
|
declare function toFieldMap(scored: Scored<FieldSuggestion>[]): Record<string, string>;
|
|
62
63
|
//#endregion
|
|
63
|
-
export { type DiscoveredColumnMeta, FieldSuggestion, RelationshipSuggestion, ScoredTable, SuggestedVia, TARGET_CONCEPTS, TargetConcept, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping };
|
|
64
|
+
export { type DiscoveredColumnMeta, FieldSuggestion, RelationshipSuggestion, ScoredTable, SuggestedVia, TARGET_CONCEPTS, TargetConcept, hasDefiningColumn, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping };
|
|
@@ -493,4 +493,4 @@ function toFieldMap(scored) {
|
|
|
493
493
|
return map;
|
|
494
494
|
}
|
|
495
495
|
//#endregion
|
|
496
|
-
export { TARGET_CONCEPTS, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping };
|
|
496
|
+
export { TARGET_CONCEPTS, hasDefiningColumn, hasSensitiveColumns, matchesConcept, requiredFieldsFor, scoreConcepts, scoreFieldMap, scoreRelationships, suggestCursorField, suggestDiscriminatorColumns, toFieldMap, topConcept, validateMapping };
|