flingit 0.0.15 → 0.0.18
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/README.md +2 -1
- package/dist/cli/commands/cron.d.ts +29 -0
- package/dist/cli/commands/cron.d.ts.map +1 -1
- package/dist/cli/commands/cron.js +54 -37
- package/dist/cli/commands/cron.js.map +1 -1
- package/dist/cli/commands/db.d.ts.map +1 -1
- package/dist/cli/commands/db.js +15 -19
- package/dist/cli/commands/db.js.map +1 -1
- package/dist/cli/commands/feedback.js +3 -3
- package/dist/cli/commands/feedback.js.map +1 -1
- package/dist/cli/commands/launch.d.ts +45 -3
- package/dist/cli/commands/launch.d.ts.map +1 -1
- package/dist/cli/commands/launch.js +39 -17
- package/dist/cli/commands/launch.js.map +1 -1
- package/dist/cli/commands/logout.d.ts +18 -0
- package/dist/cli/commands/logout.d.ts.map +1 -1
- package/dist/cli/commands/logout.js +40 -14
- package/dist/cli/commands/logout.js.map +1 -1
- package/dist/cli/commands/logs.d.ts +3 -2
- package/dist/cli/commands/logs.d.ts.map +1 -1
- package/dist/cli/commands/logs.js +26 -43
- package/dist/cli/commands/logs.js.map +1 -1
- package/dist/cli/commands/onboard.d.ts.map +1 -1
- package/dist/cli/commands/onboard.js +3 -3
- package/dist/cli/commands/onboard.js.map +1 -1
- package/dist/cli/commands/project.d.ts.map +1 -1
- package/dist/cli/commands/project.js +44 -23
- package/dist/cli/commands/project.js.map +1 -1
- package/dist/cli/commands/push.js +3 -3
- package/dist/cli/commands/push.js.map +1 -1
- package/dist/cli/commands/register.d.ts +37 -0
- package/dist/cli/commands/register.d.ts.map +1 -1
- package/dist/cli/commands/register.js +96 -74
- package/dist/cli/commands/register.js.map +1 -1
- package/dist/cli/commands/tunnel.js +2 -2
- package/dist/cli/commands/tunnel.js.map +1 -1
- package/dist/cli/commands/whoami.d.ts +18 -0
- package/dist/cli/commands/whoami.d.ts.map +1 -1
- package/dist/cli/commands/whoami.js +54 -28
- package/dist/cli/commands/whoami.js.map +1 -1
- package/dist/cli/index.js +10 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/utils/cli-io-impl.d.ts +33 -2
- package/dist/cli/utils/cli-io-impl.d.ts.map +1 -1
- package/dist/cli/utils/cli-io-impl.js +95 -14
- package/dist/cli/utils/cli-io-impl.js.map +1 -1
- package/dist/cli/utils/cli-io.d.ts +25 -9
- package/dist/cli/utils/cli-io.d.ts.map +1 -1
- package/dist/cli/utils/config.d.ts.map +1 -1
- package/dist/cli/utils/config.js +2 -2
- package/dist/cli/utils/config.js.map +1 -1
- package/dist/cli/utils/db-adapter.d.ts +59 -0
- package/dist/cli/utils/db-adapter.d.ts.map +1 -0
- package/dist/cli/utils/db-adapter.js +74 -0
- package/dist/cli/utils/db-adapter.js.map +1 -0
- package/dist/cli/utils/email.d.ts +15 -0
- package/dist/cli/utils/email.d.ts.map +1 -0
- package/dist/cli/utils/email.js +31 -0
- package/dist/cli/utils/email.js.map +1 -0
- package/dist/cli/utils/project-name.d.ts +10 -2
- package/dist/cli/utils/project-name.d.ts.map +1 -1
- package/dist/cli/utils/project-name.js +12 -6
- package/dist/cli/utils/project-name.js.map +1 -1
- package/dist/cli/utils/project.d.ts +17 -6
- package/dist/cli/utils/project.d.ts.map +1 -1
- package/dist/cli/utils/project.js +30 -36
- package/dist/cli/utils/project.js.map +1 -1
- package/dist/cli/utils/registry.d.ts +8 -6
- package/dist/cli/utils/registry.d.ts.map +1 -1
- package/dist/cli/utils/registry.js +32 -30
- package/dist/cli/utils/registry.js.map +1 -1
- package/dist/shared/constants.d.ts +16 -3
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/constants.js +16 -3
- package/dist/shared/constants.js.map +1 -1
- package/dist/worker-runtime/discord.js +1 -1
- package/dist/worker-runtime/discord.js.map +1 -1
- package/dist/worker-runtime/index.d.ts +2 -1
- package/dist/worker-runtime/index.d.ts.map +1 -1
- package/dist/worker-runtime/index.js +19 -6
- package/dist/worker-runtime/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/default/skills/fling/.hash +1 -1
- package/templates/default/skills/fling/API.md +15 -3
- package/dist/cli/commands/admin.d.ts +0 -8
- package/dist/cli/commands/admin.d.ts.map +0 -1
- package/dist/cli/commands/admin.js +0 -244
- package/dist/cli/commands/admin.js.map +0 -1
- package/dist/cli/commands/dev-worker.d.ts +0 -12
- package/dist/cli/commands/dev-worker.d.ts.map +0 -1
- package/dist/cli/commands/dev-worker.js +0 -66
- package/dist/cli/commands/dev-worker.js.map +0 -1
- package/dist/cli/commands/tun.d.ts +0 -13
- package/dist/cli/commands/tun.d.ts.map +0 -1
- package/dist/cli/commands/tun.js +0 -189
- package/dist/cli/commands/tun.js.map +0 -1
- package/dist/cli/utils/launch-io-impl.d.ts +0 -13
- package/dist/cli/utils/launch-io-impl.d.ts.map +0 -1
- package/dist/cli/utils/launch-io-impl.js +0 -51
- package/dist/cli/utils/launch-io-impl.js.map +0 -1
- package/dist/cli/utils/launch-io.d.ts +0 -42
- package/dist/cli/utils/launch-io.d.ts.map +0 -1
- package/dist/cli/utils/launch-io.js +0 -8
- package/dist/cli/utils/launch-io.js.map +0 -1
- package/dist/cli/utils/onboarding-io-impl.d.ts +0 -12
- package/dist/cli/utils/onboarding-io-impl.d.ts.map +0 -1
- package/dist/cli/utils/onboarding-io-impl.js +0 -85
- package/dist/cli/utils/onboarding-io-impl.js.map +0 -1
- package/dist/cli/utils/onboarding-io.d.ts +0 -60
- package/dist/cli/utils/onboarding-io.d.ts.map +0 -1
- package/dist/cli/utils/onboarding-io.js +0 -9
- package/dist/cli/utils/onboarding-io.js.map +0 -1
- package/dist/client/assets/index-BqVrS7t9.js +0 -40
- package/dist/client/assets/index-DSLUsCtO.css +0 -1
- package/dist/client/index.html +0 -14
- package/dist/client/vite.svg +0 -1
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export function createSqliteAdapter(factory) {
|
|
2
|
+
return {
|
|
3
|
+
open: (path, options) => {
|
|
4
|
+
const db = factory.open(path, options);
|
|
5
|
+
return createConnection(db);
|
|
6
|
+
},
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function createConnection(db) {
|
|
10
|
+
return {
|
|
11
|
+
execute: (query) => {
|
|
12
|
+
const stmt = db.prepare(query);
|
|
13
|
+
const isReader = typeof stmt.reader === "boolean" ? stmt.reader : isSelectQuery(query);
|
|
14
|
+
if (isReader) {
|
|
15
|
+
const rows = stmt.all();
|
|
16
|
+
return { kind: "select", rows };
|
|
17
|
+
}
|
|
18
|
+
const result = stmt.run();
|
|
19
|
+
return {
|
|
20
|
+
kind: "mutate",
|
|
21
|
+
changes: result.changes,
|
|
22
|
+
lastInsertRowid: result.lastInsertRowid,
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
logsTableExists: () => {
|
|
26
|
+
const row = db
|
|
27
|
+
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='_fling_logs'")
|
|
28
|
+
.get();
|
|
29
|
+
return Boolean(row);
|
|
30
|
+
},
|
|
31
|
+
queryLogs: (params) => {
|
|
32
|
+
const { sql, args } = buildLogsQuery(params);
|
|
33
|
+
const rows = db.prepare(sql).all(...args);
|
|
34
|
+
return rows;
|
|
35
|
+
},
|
|
36
|
+
close: () => {
|
|
37
|
+
db.close();
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function isSelectQuery(query) {
|
|
42
|
+
return query.trim().toUpperCase().startsWith("SELECT");
|
|
43
|
+
}
|
|
44
|
+
function buildLogsQuery(params) {
|
|
45
|
+
const conditions = [];
|
|
46
|
+
const args = [];
|
|
47
|
+
if (params.level) {
|
|
48
|
+
conditions.push("level = ?");
|
|
49
|
+
args.push(params.level);
|
|
50
|
+
}
|
|
51
|
+
if (params.since) {
|
|
52
|
+
conditions.push("timestamp >= ?");
|
|
53
|
+
args.push(params.since);
|
|
54
|
+
}
|
|
55
|
+
if (params.cron) {
|
|
56
|
+
conditions.push("cron_job = ?");
|
|
57
|
+
args.push(params.cron);
|
|
58
|
+
}
|
|
59
|
+
if (params.afterId !== undefined) {
|
|
60
|
+
conditions.push("id > ?");
|
|
61
|
+
args.push(params.afterId);
|
|
62
|
+
}
|
|
63
|
+
const lines = ["SELECT * FROM _fling_logs"];
|
|
64
|
+
if (conditions.length > 0) {
|
|
65
|
+
lines.push(`WHERE ${conditions.join(" AND ")}`);
|
|
66
|
+
}
|
|
67
|
+
lines.push(`ORDER BY ${params.orderBy} ${params.order.toUpperCase()}`);
|
|
68
|
+
if (params.limit !== undefined) {
|
|
69
|
+
lines.push("LIMIT ?");
|
|
70
|
+
args.push(params.limit);
|
|
71
|
+
}
|
|
72
|
+
return { sql: lines.join("\n"), args };
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=db-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-adapter.js","sourceRoot":"","sources":["../../../src/cli/utils/db-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI email validation utilities.
|
|
3
|
+
*
|
|
4
|
+
* Validates email format (via Zod) and rejects RFC 2606 example domains.
|
|
5
|
+
* Pure functions — no DI needed.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isExampleDomain(email: string): boolean;
|
|
8
|
+
export declare function validateEmail(raw: string): {
|
|
9
|
+
valid: true;
|
|
10
|
+
email: string;
|
|
11
|
+
} | {
|
|
12
|
+
valid: false;
|
|
13
|
+
error: string;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=email.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/email.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAItD;AAED,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,GACV;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAalE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI email validation utilities.
|
|
3
|
+
*
|
|
4
|
+
* Validates email format (via Zod) and rejects RFC 2606 example domains.
|
|
5
|
+
* Pure functions — no DI needed.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
const emailSchema = z.string().email();
|
|
9
|
+
const EXAMPLE_DOMAIN_PATTERN = /^(.*\.)?example\.(com|org|net)$/;
|
|
10
|
+
export function isExampleDomain(email) {
|
|
11
|
+
const domain = email.split("@")[1]?.toLowerCase();
|
|
12
|
+
if (!domain)
|
|
13
|
+
return false;
|
|
14
|
+
return EXAMPLE_DOMAIN_PATTERN.test(domain);
|
|
15
|
+
}
|
|
16
|
+
export function validateEmail(raw) {
|
|
17
|
+
const email = raw.trim();
|
|
18
|
+
if (!email)
|
|
19
|
+
return { valid: false, error: "Email is required." };
|
|
20
|
+
if (!emailSchema.safeParse(email).success) {
|
|
21
|
+
return { valid: false, error: "Invalid email address." };
|
|
22
|
+
}
|
|
23
|
+
if (isExampleDomain(email)) {
|
|
24
|
+
return {
|
|
25
|
+
valid: false,
|
|
26
|
+
error: "Example domains (example.com, example.org, example.net) are not allowed.",
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return { valid: true, email };
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=email.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email.js","sourceRoot":"","sources":["../../../src/cli/utils/email.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;AACvC,MAAM,sBAAsB,GAAG,iCAAiC,CAAC;AAEjE,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;IAClD,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,OAAO,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,GAAW;IAEX,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC;IACjE,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;QAC1C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC;IAC3D,CAAC;IACD,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,0EAA0E;SAClF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAChC,CAAC"}
|
|
@@ -3,15 +3,23 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Reads the project name from package.json, with backwards compatibility
|
|
5
5
|
* for projects that don't have a projectName set.
|
|
6
|
+
* Uses dependency injection for testability.
|
|
6
7
|
*/
|
|
7
8
|
import { DEFAULT_PROJECT_NAME } from "../../shared/constants.js";
|
|
9
|
+
import type { FileIO, ReadFileString } from "./cli-io.js";
|
|
8
10
|
export { DEFAULT_PROJECT_NAME };
|
|
11
|
+
/**
|
|
12
|
+
* File operations needed for reading project name.
|
|
13
|
+
*/
|
|
14
|
+
export type ProjectNameFileIO = FileIO & ReadFileString;
|
|
9
15
|
/**
|
|
10
16
|
* Read the project name from package.json's fling.projectName field.
|
|
11
17
|
* Returns DEFAULT_PROJECT_NAME if the field is not present (backwards compatibility).
|
|
12
18
|
*
|
|
13
|
-
* @param
|
|
19
|
+
* @param file - File I/O operations
|
|
20
|
+
* @param cwd - Function to get current working directory
|
|
21
|
+
* @param projectDir - The project directory (defaults to cwd())
|
|
14
22
|
* @returns The project name, or DEFAULT_PROJECT_NAME if not set
|
|
15
23
|
*/
|
|
16
|
-
export declare function getProjectName(projectDir?: string): string;
|
|
24
|
+
export declare function getProjectName(file: ProjectNameFileIO, cwd: () => string, projectDir?: string): string;
|
|
17
25
|
//# sourceMappingURL=project-name.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-name.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/project-name.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"project-name.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/project-name.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG1D,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAQhC;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,cAAc,CAAC;AAExD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,iBAAiB,EACvB,GAAG,EAAE,MAAM,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,CAmBR"}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Reads the project name from package.json, with backwards compatibility
|
|
5
5
|
* for projects that don't have a projectName set.
|
|
6
|
+
* Uses dependency injection for testability.
|
|
6
7
|
*/
|
|
7
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
8
8
|
import { join } from "node:path";
|
|
9
9
|
import { DEFAULT_PROJECT_NAME } from "../../shared/constants.js";
|
|
10
10
|
// Re-export for consumers
|
|
@@ -13,16 +13,22 @@ export { DEFAULT_PROJECT_NAME };
|
|
|
13
13
|
* Read the project name from package.json's fling.projectName field.
|
|
14
14
|
* Returns DEFAULT_PROJECT_NAME if the field is not present (backwards compatibility).
|
|
15
15
|
*
|
|
16
|
-
* @param
|
|
16
|
+
* @param file - File I/O operations
|
|
17
|
+
* @param cwd - Function to get current working directory
|
|
18
|
+
* @param projectDir - The project directory (defaults to cwd())
|
|
17
19
|
* @returns The project name, or DEFAULT_PROJECT_NAME if not set
|
|
18
20
|
*/
|
|
19
|
-
export function getProjectName(
|
|
20
|
-
const
|
|
21
|
-
|
|
21
|
+
export function getProjectName(file, cwd, projectDir) {
|
|
22
|
+
const dir = projectDir ?? cwd();
|
|
23
|
+
const packageJsonPath = join(dir, "package.json");
|
|
24
|
+
if (!file.exists(packageJsonPath)) {
|
|
25
|
+
return DEFAULT_PROJECT_NAME;
|
|
26
|
+
}
|
|
27
|
+
const content = file.readFileString(packageJsonPath);
|
|
28
|
+
if (content === null) {
|
|
22
29
|
return DEFAULT_PROJECT_NAME;
|
|
23
30
|
}
|
|
24
31
|
try {
|
|
25
|
-
const content = readFileSync(packageJsonPath, "utf-8");
|
|
26
32
|
const pkg = JSON.parse(content);
|
|
27
33
|
return pkg.fling?.projectName ?? DEFAULT_PROJECT_NAME;
|
|
28
34
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-name.js","sourceRoot":"","sources":["../../../src/cli/utils/project-name.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"project-name.js","sourceRoot":"","sources":["../../../src/cli/utils/project-name.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAGjE,0BAA0B;AAC1B,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAahC;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAuB,EACvB,GAAiB,EACjB,UAAmB;IAEnB,MAAM,GAAG,GAAG,UAAU,IAAI,GAAG,EAAE,CAAC;IAChC,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAElD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC;QAClC,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;IACrD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAgB,CAAC;QAC/C,OAAO,GAAG,CAAC,KAAK,EAAE,WAAW,IAAI,oBAAoB,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,oBAAoB,CAAC;IAC9B,CAAC;AACH,CAAC"}
|
|
@@ -2,12 +2,23 @@
|
|
|
2
2
|
* Project utility functions.
|
|
3
3
|
*
|
|
4
4
|
* Provides helpers for locating project files and validating project structure.
|
|
5
|
+
* All functions accept dependency-injected I/O interfaces for testability.
|
|
5
6
|
*/
|
|
7
|
+
import type { ProjectFileIO } from "./cli-io.js";
|
|
6
8
|
/**
|
|
7
|
-
*
|
|
9
|
+
* Dependencies for getFlingRoot.
|
|
10
|
+
*/
|
|
11
|
+
export interface GetFlingRootDeps {
|
|
12
|
+
file: ProjectFileIO;
|
|
13
|
+
moduleFilePath: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Get Fling root directory by walking up from the module file to find package.json.
|
|
8
17
|
* Verifies the package name is "flingit" to ensure we found the right one.
|
|
18
|
+
*
|
|
19
|
+
* Note: Caching is handled by the caller (cli-io-impl.ts) rather than internally.
|
|
9
20
|
*/
|
|
10
|
-
export declare function getFlingRoot(): string;
|
|
21
|
+
export declare function getFlingRoot(deps: GetFlingRootDeps): string;
|
|
11
22
|
/**
|
|
12
23
|
* Result of checking skills update status.
|
|
13
24
|
*/
|
|
@@ -65,20 +76,20 @@ export declare function getWorkerEntryPath(projectDir: string): string;
|
|
|
65
76
|
/**
|
|
66
77
|
* Check if worker entry point exists.
|
|
67
78
|
*/
|
|
68
|
-
export declare function hasWorkerEntry(projectDir: string): boolean;
|
|
79
|
+
export declare function hasWorkerEntry(projectDir: string, file: ProjectFileIO): boolean;
|
|
69
80
|
/**
|
|
70
81
|
* Check if a directory is a Fling project root (has a fling Claude skill).
|
|
71
82
|
*/
|
|
72
|
-
export declare function isProjectRoot(dir: string): boolean;
|
|
83
|
+
export declare function isProjectRoot(dir: string, file: ProjectFileIO): boolean;
|
|
73
84
|
/**
|
|
74
85
|
* Walk up from startDir looking for an enclosing Fling project.
|
|
75
86
|
* Returns the project root path, or null if none found.
|
|
76
87
|
*/
|
|
77
|
-
export declare function findEnclosingProject(startDir: string): string | null;
|
|
88
|
+
export declare function findEnclosingProject(startDir: string, file: ProjectFileIO): string | null;
|
|
78
89
|
/**
|
|
79
90
|
* Check if any component of a path is a symlink.
|
|
80
91
|
* Walks from the target path up to (but not including) the base path.
|
|
81
92
|
* This only checks symlinks within the project, not above it.
|
|
82
93
|
*/
|
|
83
|
-
export declare function hasSymlinkInPath(targetPath: string, basePath: string): boolean;
|
|
94
|
+
export declare function hasSymlinkInPath(targetPath: string, basePath: string, file: ProjectFileIO): boolean;
|
|
84
95
|
//# sourceMappingURL=project.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/project.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/project.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,aAAa,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAwB3D;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,MAAM,EAAE,gBAAgB,CAAA;CAAE,GAC5B;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACtD,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAChE,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CAC7C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,cAAc,GACjB,YAAY,CAgCd;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,yCAA0C,CAAC;AAEzE;;GAEG;AACH,eAAO,MAAM,oBAAoB,8BAA+B,CAAC;AAEjE;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAE/E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAEvE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAezF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAmBnG"}
|
|
@@ -2,36 +2,32 @@
|
|
|
2
2
|
* Project utility functions.
|
|
3
3
|
*
|
|
4
4
|
* Provides helpers for locating project files and validating project structure.
|
|
5
|
+
* All functions accept dependency-injected I/O interfaces for testability.
|
|
5
6
|
*/
|
|
6
|
-
import { existsSync, lstatSync, readFileSync } from "node:fs";
|
|
7
7
|
import { join, dirname, resolve } from "node:path";
|
|
8
|
-
import { fileURLToPath } from "node:url";
|
|
9
|
-
// Cache the result since it won't change during execution
|
|
10
|
-
let cachedFlingRoot = null;
|
|
11
8
|
/**
|
|
12
|
-
* Get Fling root directory by walking up from
|
|
9
|
+
* Get Fling root directory by walking up from the module file to find package.json.
|
|
13
10
|
* Verifies the package name is "flingit" to ensure we found the right one.
|
|
11
|
+
*
|
|
12
|
+
* Note: Caching is handled by the caller (cli-io-impl.ts) rather than internally.
|
|
14
13
|
*/
|
|
15
|
-
export function getFlingRoot() {
|
|
16
|
-
|
|
17
|
-
return cachedFlingRoot;
|
|
18
|
-
}
|
|
19
|
-
const thisFile = fileURLToPath(import.meta.url);
|
|
20
|
-
let current = dirname(thisFile);
|
|
14
|
+
export function getFlingRoot(deps) {
|
|
15
|
+
let current = dirname(deps.moduleFilePath);
|
|
21
16
|
let parent = dirname(current);
|
|
22
17
|
while (current !== parent) {
|
|
23
18
|
const packageJsonPath = join(current, "package.json");
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
19
|
+
if (deps.file.exists(packageJsonPath)) {
|
|
20
|
+
const content = deps.file.readFileString(packageJsonPath);
|
|
21
|
+
if (content !== null) {
|
|
22
|
+
try {
|
|
23
|
+
const pkg = JSON.parse(content);
|
|
24
|
+
if (pkg.name === "flingit") {
|
|
25
|
+
return current;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// Invalid JSON, keep looking
|
|
31
30
|
}
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
// Invalid JSON, keep looking
|
|
35
31
|
}
|
|
36
32
|
}
|
|
37
33
|
current = parent;
|
|
@@ -100,31 +96,31 @@ export function getWorkerEntryPath(projectDir) {
|
|
|
100
96
|
/**
|
|
101
97
|
* Check if worker entry point exists.
|
|
102
98
|
*/
|
|
103
|
-
export function hasWorkerEntry(projectDir) {
|
|
104
|
-
return
|
|
99
|
+
export function hasWorkerEntry(projectDir, file) {
|
|
100
|
+
return file.exists(getWorkerEntryPath(projectDir));
|
|
105
101
|
}
|
|
106
102
|
/**
|
|
107
103
|
* Check if a directory is a Fling project root (has a fling Claude skill).
|
|
108
104
|
*/
|
|
109
|
-
export function isProjectRoot(dir) {
|
|
110
|
-
return
|
|
105
|
+
export function isProjectRoot(dir, file) {
|
|
106
|
+
return file.exists(getProjectSkillsDir(dir));
|
|
111
107
|
}
|
|
112
108
|
/**
|
|
113
109
|
* Walk up from startDir looking for an enclosing Fling project.
|
|
114
110
|
* Returns the project root path, or null if none found.
|
|
115
111
|
*/
|
|
116
|
-
export function findEnclosingProject(startDir) {
|
|
112
|
+
export function findEnclosingProject(startDir, file) {
|
|
117
113
|
let current = resolve(startDir);
|
|
118
114
|
let parent = dirname(current);
|
|
119
115
|
while (current !== parent) {
|
|
120
|
-
if (isProjectRoot(current)) {
|
|
116
|
+
if (isProjectRoot(current, file)) {
|
|
121
117
|
return current;
|
|
122
118
|
}
|
|
123
119
|
current = parent;
|
|
124
120
|
parent = dirname(current);
|
|
125
121
|
}
|
|
126
122
|
// Check the filesystem root itself
|
|
127
|
-
if (isProjectRoot(current)) {
|
|
123
|
+
if (isProjectRoot(current, file)) {
|
|
128
124
|
return current;
|
|
129
125
|
}
|
|
130
126
|
return null;
|
|
@@ -134,21 +130,19 @@ export function findEnclosingProject(startDir) {
|
|
|
134
130
|
* Walks from the target path up to (but not including) the base path.
|
|
135
131
|
* This only checks symlinks within the project, not above it.
|
|
136
132
|
*/
|
|
137
|
-
export function hasSymlinkInPath(targetPath, basePath) {
|
|
133
|
+
export function hasSymlinkInPath(targetPath, basePath, file) {
|
|
138
134
|
let current = targetPath;
|
|
139
135
|
let parent = dirname(current);
|
|
140
136
|
// Stop when we reach the base path (don't check it or above)
|
|
141
137
|
while (current !== parent && current !== basePath) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (stats.isSymbolicLink()) {
|
|
145
|
-
return true;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
catch {
|
|
138
|
+
const stats = file.lstat(current);
|
|
139
|
+
if (stats === null) {
|
|
149
140
|
// Path doesn't exist, stop checking
|
|
150
141
|
break;
|
|
151
142
|
}
|
|
143
|
+
if (stats.isSymbolicLink()) {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
152
146
|
current = parent;
|
|
153
147
|
parent = dirname(current);
|
|
154
148
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../../src/cli/utils/project.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../../src/cli/utils/project.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,33 +2,35 @@
|
|
|
2
2
|
* Project registry utilities.
|
|
3
3
|
* Manages a list of known Fling project paths in ~/.config/fling/projects.json
|
|
4
4
|
* (XDG Base Directory spec, or FLING_CONFIG_DIR if set).
|
|
5
|
+
* Uses dependency injection for testability.
|
|
5
6
|
*/
|
|
7
|
+
import type { RegistryIO } from "./cli-io.js";
|
|
6
8
|
/**
|
|
7
9
|
* Read the project registry. Returns an empty array if the file
|
|
8
10
|
* is missing or malformed.
|
|
9
11
|
*/
|
|
10
|
-
export declare function readRegistry(): string[];
|
|
12
|
+
export declare function readRegistry(io: RegistryIO): string[];
|
|
11
13
|
/**
|
|
12
14
|
* Write the project registry.
|
|
13
15
|
*/
|
|
14
|
-
export declare function writeRegistry(projects: string[]): void;
|
|
16
|
+
export declare function writeRegistry(projects: string[], io: RegistryIO): void;
|
|
15
17
|
/**
|
|
16
18
|
* Register a project path. Idempotent — resolves to absolute path
|
|
17
19
|
* before storing.
|
|
18
20
|
*/
|
|
19
|
-
export declare function registerProject(projectPath: string): void;
|
|
21
|
+
export declare function registerProject(projectPath: string, io: RegistryIO): void;
|
|
20
22
|
/**
|
|
21
23
|
* Unregister a project path.
|
|
22
24
|
*/
|
|
23
|
-
export declare function unregisterProject(projectPath: string): void;
|
|
25
|
+
export declare function unregisterProject(projectPath: string, io: RegistryIO): void;
|
|
24
26
|
/**
|
|
25
27
|
* Get valid projects — those whose directories still exist and
|
|
26
28
|
* contain a .fling/ subdirectory. Stale entries are auto-pruned
|
|
27
29
|
* from the registry file.
|
|
28
30
|
*/
|
|
29
|
-
export declare function getValidProjects(): string[];
|
|
31
|
+
export declare function getValidProjects(io: RegistryIO): string[];
|
|
30
32
|
/**
|
|
31
33
|
* Check if a path is registered.
|
|
32
34
|
*/
|
|
33
|
-
export declare function isRegistered(projectPath: string): boolean;
|
|
35
|
+
export declare function isRegistered(projectPath: string, io: RegistryIO): boolean;
|
|
34
36
|
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/registry.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAS,UAAU,EAAE,MAAM,aAAa,CAAC;AA6BrD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,UAAU,GAAG,MAAM,EAAE,CAkBrD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,UAAU,GAAG,IAAI,CAOtE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,GAAG,IAAI,CAOzE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,GAAG,IAAI,CAO3E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,UAAU,GAAG,MAAM,EAAE,CASzD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,GAAG,OAAO,CAGzE"}
|
|
@@ -2,42 +2,44 @@
|
|
|
2
2
|
* Project registry utilities.
|
|
3
3
|
* Manages a list of known Fling project paths in ~/.config/fling/projects.json
|
|
4
4
|
* (XDG Base Directory spec, or FLING_CONFIG_DIR if set).
|
|
5
|
+
* Uses dependency injection for testability.
|
|
5
6
|
*/
|
|
6
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { join, resolve } from "node:path";
|
|
8
|
-
import { homedir } from "node:os";
|
|
9
|
-
import { isProjectRoot } from "./project.js";
|
|
10
8
|
/**
|
|
11
9
|
* Get the configuration directory.
|
|
12
10
|
* Priority: FLING_CONFIG_DIR > XDG_CONFIG_HOME/fling > ~/.config/fling
|
|
13
11
|
* Note: Migration is handled by config.ts; registry just reads the same location.
|
|
14
12
|
*/
|
|
15
|
-
function getConfigDir() {
|
|
16
|
-
const envDir =
|
|
13
|
+
function getConfigDir(env) {
|
|
14
|
+
const envDir = env.get("FLING_CONFIG_DIR");
|
|
17
15
|
if (envDir) {
|
|
18
16
|
return envDir;
|
|
19
17
|
}
|
|
20
18
|
// Respect XDG_CONFIG_HOME if set, otherwise default to ~/.config/fling
|
|
21
|
-
const xdgConfig =
|
|
19
|
+
const xdgConfig = env.get("XDG_CONFIG_HOME");
|
|
22
20
|
if (xdgConfig) {
|
|
23
21
|
return join(xdgConfig, "fling");
|
|
24
22
|
}
|
|
25
|
-
return join(homedir(), ".config", "fling");
|
|
23
|
+
return join(env.homedir(), ".config", "fling");
|
|
26
24
|
}
|
|
27
|
-
function getRegistryPath() {
|
|
28
|
-
return join(getConfigDir(), "projects.json");
|
|
25
|
+
function getRegistryPath(env) {
|
|
26
|
+
return join(getConfigDir(env), "projects.json");
|
|
29
27
|
}
|
|
30
28
|
/**
|
|
31
29
|
* Read the project registry. Returns an empty array if the file
|
|
32
30
|
* is missing or malformed.
|
|
33
31
|
*/
|
|
34
|
-
export function readRegistry() {
|
|
35
|
-
const registryPath = getRegistryPath();
|
|
36
|
-
if (!
|
|
32
|
+
export function readRegistry(io) {
|
|
33
|
+
const registryPath = getRegistryPath(io.env);
|
|
34
|
+
if (!io.file.exists(registryPath)) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
const content = io.file.readFileString(registryPath);
|
|
38
|
+
if (content === null) {
|
|
37
39
|
return [];
|
|
38
40
|
}
|
|
39
41
|
try {
|
|
40
|
-
const data = JSON.parse(
|
|
42
|
+
const data = JSON.parse(content);
|
|
41
43
|
if (Array.isArray(data.projects)) {
|
|
42
44
|
return data.projects;
|
|
43
45
|
}
|
|
@@ -50,35 +52,35 @@ export function readRegistry() {
|
|
|
50
52
|
/**
|
|
51
53
|
* Write the project registry.
|
|
52
54
|
*/
|
|
53
|
-
export function writeRegistry(projects) {
|
|
54
|
-
const configDir = getConfigDir();
|
|
55
|
-
if (!
|
|
56
|
-
|
|
55
|
+
export function writeRegistry(projects, io) {
|
|
56
|
+
const configDir = getConfigDir(io.env);
|
|
57
|
+
if (!io.file.exists(configDir)) {
|
|
58
|
+
io.file.mkdir(configDir, { recursive: true });
|
|
57
59
|
}
|
|
58
60
|
const data = { projects };
|
|
59
|
-
|
|
61
|
+
io.file.writeFileString(getRegistryPath(io.env), JSON.stringify(data, null, 2) + "\n");
|
|
60
62
|
}
|
|
61
63
|
/**
|
|
62
64
|
* Register a project path. Idempotent — resolves to absolute path
|
|
63
65
|
* before storing.
|
|
64
66
|
*/
|
|
65
|
-
export function registerProject(projectPath) {
|
|
67
|
+
export function registerProject(projectPath, io) {
|
|
66
68
|
const abs = resolve(projectPath);
|
|
67
|
-
const projects = readRegistry();
|
|
69
|
+
const projects = readRegistry(io);
|
|
68
70
|
if (!projects.includes(abs)) {
|
|
69
71
|
projects.push(abs);
|
|
70
|
-
writeRegistry(projects);
|
|
72
|
+
writeRegistry(projects, io);
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
/**
|
|
74
76
|
* Unregister a project path.
|
|
75
77
|
*/
|
|
76
|
-
export function unregisterProject(projectPath) {
|
|
78
|
+
export function unregisterProject(projectPath, io) {
|
|
77
79
|
const abs = resolve(projectPath);
|
|
78
|
-
const projects = readRegistry();
|
|
80
|
+
const projects = readRegistry(io);
|
|
79
81
|
const filtered = projects.filter((p) => p !== abs);
|
|
80
82
|
if (filtered.length !== projects.length) {
|
|
81
|
-
writeRegistry(filtered);
|
|
83
|
+
writeRegistry(filtered, io);
|
|
82
84
|
}
|
|
83
85
|
}
|
|
84
86
|
/**
|
|
@@ -86,19 +88,19 @@ export function unregisterProject(projectPath) {
|
|
|
86
88
|
* contain a .fling/ subdirectory. Stale entries are auto-pruned
|
|
87
89
|
* from the registry file.
|
|
88
90
|
*/
|
|
89
|
-
export function getValidProjects() {
|
|
90
|
-
const projects = readRegistry();
|
|
91
|
-
const valid = projects.filter((p) =>
|
|
91
|
+
export function getValidProjects(io) {
|
|
92
|
+
const projects = readRegistry(io);
|
|
93
|
+
const valid = projects.filter((p) => io.file.exists(p) && io.isProjectRoot(p));
|
|
92
94
|
if (valid.length !== projects.length) {
|
|
93
|
-
writeRegistry(valid);
|
|
95
|
+
writeRegistry(valid, io);
|
|
94
96
|
}
|
|
95
97
|
return valid;
|
|
96
98
|
}
|
|
97
99
|
/**
|
|
98
100
|
* Check if a path is registered.
|
|
99
101
|
*/
|
|
100
|
-
export function isRegistered(projectPath) {
|
|
102
|
+
export function isRegistered(projectPath, io) {
|
|
101
103
|
const abs = resolve(projectPath);
|
|
102
|
-
return readRegistry().includes(abs);
|
|
104
|
+
return readRegistry(io).includes(abs);
|
|
103
105
|
}
|
|
104
106
|
//# sourceMappingURL=registry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/cli/utils/registry.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/cli/utils/registry.ts"],"names":[],"mappings":"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"}
|