semola 0.5.0 → 0.5.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/README.md +75 -20
- package/dist/api/core/index.cjs +206 -0
- package/dist/api/core/index.d.cts +21 -0
- package/dist/api/core/index.d.cts.map +1 -0
- package/dist/api/core/index.d.mts +21 -0
- package/dist/api/core/index.d.mts.map +1 -0
- package/dist/api/core/index.mjs +208 -0
- package/dist/api/core/index.mjs.map +1 -0
- package/dist/api/core/types.d.cts +107 -0
- package/dist/api/core/types.d.cts.map +1 -0
- package/dist/api/core/types.d.mts +107 -0
- package/dist/api/core/types.d.mts.map +1 -0
- package/dist/api/middleware/index.cjs +8 -0
- package/dist/api/middleware/index.d.cts +11 -0
- package/dist/api/middleware/index.d.cts.map +1 -0
- package/dist/api/middleware/index.d.mts +11 -0
- package/dist/api/middleware/index.d.mts.map +1 -0
- package/dist/api/middleware/index.mjs +10 -0
- package/dist/api/middleware/index.mjs.map +1 -0
- package/dist/api/middleware/types.d.cts +16 -0
- package/dist/api/middleware/types.d.cts.map +1 -0
- package/dist/api/middleware/types.d.mts +16 -0
- package/dist/api/middleware/types.d.mts.map +1 -0
- package/dist/api/openapi/index.cjs +254 -0
- package/dist/api/openapi/index.mjs +256 -0
- package/dist/api/openapi/index.mjs.map +1 -0
- package/dist/api/openapi/types.d.cts +60 -0
- package/dist/api/openapi/types.d.cts.map +1 -0
- package/dist/api/openapi/types.d.mts +60 -0
- package/dist/api/openapi/types.d.mts.map +1 -0
- package/dist/api/validation/index.cjs +64 -0
- package/dist/api/validation/index.mjs +61 -0
- package/dist/api/validation/index.mjs.map +1 -0
- package/dist/cache/types.d.cts +17 -0
- package/dist/cache/types.d.cts.map +1 -0
- package/dist/cache/types.d.mts +17 -0
- package/dist/cache/types.d.mts.map +1 -0
- package/dist/cron/scanner.cjs +237 -0
- package/dist/cron/scanner.mjs +238 -0
- package/dist/cron/scanner.mjs.map +1 -0
- package/dist/cron/types.d.cts +11 -0
- package/dist/cron/types.d.cts.map +1 -0
- package/dist/cron/types.d.mts +11 -0
- package/dist/cron/types.d.mts.map +1 -0
- package/dist/errors/types.d.cts +5 -0
- package/dist/errors/types.d.cts.map +1 -0
- package/dist/errors/types.d.mts +5 -0
- package/dist/errors/types.d.mts.map +1 -0
- package/dist/i18n/types.d.cts +13 -0
- package/dist/i18n/types.d.cts.map +1 -0
- package/dist/i18n/types.d.mts +13 -0
- package/dist/i18n/types.d.mts.map +1 -0
- package/dist/lib/api/index.cjs +5 -0
- package/dist/lib/api/index.d.cts +5 -0
- package/dist/lib/api/index.d.mts +5 -0
- package/dist/lib/api/index.mjs +3 -0
- package/dist/lib/cache/index.cjs +74 -0
- package/dist/lib/cache/index.d.cts +36 -0
- package/dist/lib/cache/index.d.cts.map +1 -0
- package/dist/lib/cache/index.d.mts +36 -0
- package/dist/lib/cache/index.d.mts.map +1 -0
- package/dist/lib/cache/index.mjs +75 -0
- package/dist/lib/cache/index.mjs.map +1 -0
- package/dist/lib/cron/index.cjs +276 -0
- package/dist/lib/cron/index.d.cts +39 -0
- package/dist/lib/cron/index.d.cts.map +1 -0
- package/dist/lib/cron/index.d.mts +39 -0
- package/dist/lib/cron/index.d.mts.map +1 -0
- package/dist/lib/cron/index.mjs +277 -0
- package/dist/lib/cron/index.mjs.map +1 -0
- package/dist/lib/errors/index.cjs +30 -0
- package/dist/lib/errors/index.d.cts +13 -0
- package/dist/lib/errors/index.d.cts.map +1 -0
- package/dist/lib/errors/index.d.mts +13 -0
- package/dist/lib/errors/index.d.mts.map +1 -0
- package/dist/lib/errors/index.mjs +28 -0
- package/dist/lib/errors/index.mjs.map +1 -0
- package/dist/lib/i18n/index.cjs +37 -0
- package/dist/lib/i18n/index.d.cts +20 -0
- package/dist/lib/i18n/index.d.cts.map +1 -0
- package/dist/lib/i18n/index.d.mts +20 -0
- package/dist/lib/i18n/index.d.mts.map +1 -0
- package/dist/lib/i18n/index.mjs +38 -0
- package/dist/lib/i18n/index.mjs.map +1 -0
- package/dist/lib/policy/index.cjs +99 -0
- package/dist/lib/policy/index.d.cts +21 -0
- package/dist/lib/policy/index.d.cts.map +1 -0
- package/dist/lib/policy/index.d.mts +21 -0
- package/dist/lib/policy/index.d.mts.map +1 -0
- package/dist/lib/policy/index.mjs +81 -0
- package/dist/lib/policy/index.mjs.map +1 -0
- package/dist/lib/prompts/index.cjs +409 -0
- package/dist/lib/prompts/index.d.cts +31 -0
- package/dist/lib/prompts/index.d.cts.map +1 -0
- package/dist/lib/prompts/index.d.mts +31 -0
- package/dist/lib/prompts/index.d.mts.map +1 -0
- package/dist/lib/prompts/index.mjs +405 -0
- package/dist/lib/prompts/index.mjs.map +1 -0
- package/dist/lib/pubsub/index.cjs +48 -0
- package/dist/lib/pubsub/index.d.cts +27 -0
- package/dist/lib/pubsub/index.d.cts.map +1 -0
- package/dist/lib/pubsub/index.d.mts +27 -0
- package/dist/lib/pubsub/index.d.mts.map +1 -0
- package/dist/lib/pubsub/index.mjs +49 -0
- package/dist/lib/pubsub/index.mjs.map +1 -0
- package/dist/lib/queue/index.cjs +182 -0
- package/dist/lib/queue/index.d.cts +32 -0
- package/dist/lib/queue/index.d.cts.map +1 -0
- package/dist/lib/queue/index.d.mts +32 -0
- package/dist/lib/queue/index.d.mts.map +1 -0
- package/dist/lib/queue/index.mjs +183 -0
- package/dist/lib/queue/index.mjs.map +1 -0
- package/dist/node_modules/@standard-schema/spec/dist/index.d.cts +80 -0
- package/dist/node_modules/@standard-schema/spec/dist/index.d.cts.map +1 -0
- package/dist/node_modules/@standard-schema/spec/dist/index.d.mts +80 -0
- package/dist/node_modules/@standard-schema/spec/dist/index.d.mts.map +1 -0
- package/dist/policy/helpers.cjs +206 -0
- package/dist/policy/helpers.d.cts +50 -0
- package/dist/policy/helpers.d.cts.map +1 -0
- package/dist/policy/helpers.d.mts +50 -0
- package/dist/policy/helpers.d.mts.map +1 -0
- package/dist/policy/helpers.mjs +190 -0
- package/dist/policy/helpers.mjs.map +1 -0
- package/dist/policy/types.d.cts +16 -0
- package/dist/policy/types.d.cts.map +1 -0
- package/dist/policy/types.d.mts +16 -0
- package/dist/policy/types.d.mts.map +1 -0
- package/dist/prompts/core/keys.cjs +165 -0
- package/dist/prompts/core/keys.mjs +167 -0
- package/dist/prompts/core/keys.mjs.map +1 -0
- package/dist/prompts/core/runtime.cjs +104 -0
- package/dist/prompts/core/runtime.mjs +106 -0
- package/dist/prompts/core/runtime.mjs.map +1 -0
- package/dist/prompts/core/session.cjs +98 -0
- package/dist/prompts/core/session.mjs +100 -0
- package/dist/prompts/core/session.mjs.map +1 -0
- package/dist/prompts/core/types.d.cts +21 -0
- package/dist/prompts/core/types.d.cts.map +1 -0
- package/dist/prompts/core/types.d.mts +21 -0
- package/dist/prompts/core/types.d.mts.map +1 -0
- package/dist/prompts/types.d.cts +52 -0
- package/dist/prompts/types.d.cts.map +1 -0
- package/dist/prompts/types.d.mts +52 -0
- package/dist/prompts/types.d.mts.map +1 -0
- package/dist/pubsub/types.d.cts +10 -0
- package/dist/pubsub/types.d.cts.map +1 -0
- package/dist/pubsub/types.d.mts +10 -0
- package/dist/pubsub/types.d.mts.map +1 -0
- package/dist/queue/types.d.cts +47 -0
- package/dist/queue/types.d.cts.map +1 -0
- package/dist/queue/types.d.mts +47 -0
- package/dist/queue/types.d.mts.map +1 -0
- package/package.json +86 -16
- package/dist/lib/api/core/index.d.ts +0 -15
- package/dist/lib/api/core/index.d.ts.map +0 -1
- package/dist/lib/api/core/index.js +0 -166
- package/dist/lib/api/core/index.js.map +0 -1
- package/dist/lib/api/core/index.test.d.ts +0 -2
- package/dist/lib/api/core/index.test.d.ts.map +0 -1
- package/dist/lib/api/core/index.test.js +0 -219
- package/dist/lib/api/core/index.test.js.map +0 -1
- package/dist/lib/api/core/types.d.ts +0 -102
- package/dist/lib/api/core/types.d.ts.map +0 -1
- package/dist/lib/api/core/types.js +0 -2
- package/dist/lib/api/core/types.js.map +0 -1
- package/dist/lib/api/index.d.ts +0 -5
- package/dist/lib/api/index.d.ts.map +0 -1
- package/dist/lib/api/index.js +0 -3
- package/dist/lib/api/index.js.map +0 -1
- package/dist/lib/api/middleware/index.d.ts +0 -7
- package/dist/lib/api/middleware/index.d.ts.map +0 -1
- package/dist/lib/api/middleware/index.js +0 -7
- package/dist/lib/api/middleware/index.js.map +0 -1
- package/dist/lib/api/middleware/index.test.d.ts +0 -2
- package/dist/lib/api/middleware/index.test.d.ts.map +0 -1
- package/dist/lib/api/middleware/index.test.js +0 -67
- package/dist/lib/api/middleware/index.test.js.map +0 -1
- package/dist/lib/api/middleware/types.d.ts +0 -12
- package/dist/lib/api/middleware/types.d.ts.map +0 -1
- package/dist/lib/api/middleware/types.js +0 -2
- package/dist/lib/api/middleware/types.js.map +0 -1
- package/dist/lib/api/openapi/index.d.ts +0 -31
- package/dist/lib/api/openapi/index.d.ts.map +0 -1
- package/dist/lib/api/openapi/index.js +0 -328
- package/dist/lib/api/openapi/index.js.map +0 -1
- package/dist/lib/api/openapi/index.test.d.ts +0 -2
- package/dist/lib/api/openapi/index.test.d.ts.map +0 -1
- package/dist/lib/api/openapi/index.test.js +0 -359
- package/dist/lib/api/openapi/index.test.js.map +0 -1
- package/dist/lib/api/openapi/types.d.ts +0 -57
- package/dist/lib/api/openapi/types.d.ts.map +0 -1
- package/dist/lib/api/openapi/types.js +0 -5
- package/dist/lib/api/openapi/types.js.map +0 -1
- package/dist/lib/api/validation/index.d.ts +0 -33
- package/dist/lib/api/validation/index.d.ts.map +0 -1
- package/dist/lib/api/validation/index.js +0 -81
- package/dist/lib/api/validation/index.js.map +0 -1
- package/dist/lib/api/validation/index.test.d.ts +0 -2
- package/dist/lib/api/validation/index.test.d.ts.map +0 -1
- package/dist/lib/api/validation/index.test.js +0 -135
- package/dist/lib/api/validation/index.test.js.map +0 -1
- package/dist/lib/cache/index.d.ts +0 -25
- package/dist/lib/cache/index.d.ts.map +0 -1
- package/dist/lib/cache/index.js +0 -62
- package/dist/lib/cache/index.js.map +0 -1
- package/dist/lib/cache/index.test.d.ts +0 -2
- package/dist/lib/cache/index.test.d.ts.map +0 -1
- package/dist/lib/cache/index.test.js +0 -314
- package/dist/lib/cache/index.test.js.map +0 -1
- package/dist/lib/cache/types.d.ts +0 -5
- package/dist/lib/cache/types.d.ts.map +0 -1
- package/dist/lib/cache/types.js +0 -2
- package/dist/lib/cache/types.js.map +0 -1
- package/dist/lib/errors/index.d.ts +0 -9
- package/dist/lib/errors/index.d.ts.map +0 -1
- package/dist/lib/errors/index.js +0 -25
- package/dist/lib/errors/index.js.map +0 -1
- package/dist/lib/errors/index.test.d.ts +0 -2
- package/dist/lib/errors/index.test.d.ts.map +0 -1
- package/dist/lib/errors/index.test.js +0 -197
- package/dist/lib/errors/index.test.js.map +0 -1
- package/dist/lib/errors/types.d.ts +0 -2
- package/dist/lib/errors/types.d.ts.map +0 -1
- package/dist/lib/errors/types.js +0 -2
- package/dist/lib/errors/types.js.map +0 -1
- package/dist/lib/i18n/index.d.ts +0 -18
- package/dist/lib/i18n/index.d.ts.map +0 -1
- package/dist/lib/i18n/index.js +0 -38
- package/dist/lib/i18n/index.js.map +0 -1
- package/dist/lib/i18n/index.test.d.ts +0 -2
- package/dist/lib/i18n/index.test.d.ts.map +0 -1
- package/dist/lib/i18n/index.test.js +0 -402
- package/dist/lib/i18n/index.test.js.map +0 -1
- package/dist/lib/i18n/types.d.ts +0 -15
- package/dist/lib/i18n/types.d.ts.map +0 -1
- package/dist/lib/i18n/types.js +0 -2
- package/dist/lib/i18n/types.js.map +0 -1
- package/dist/lib/policy/index.d.ts +0 -9
- package/dist/lib/policy/index.d.ts.map +0 -1
- package/dist/lib/policy/index.js +0 -51
- package/dist/lib/policy/index.js.map +0 -1
- package/dist/lib/policy/index.test.d.ts +0 -2
- package/dist/lib/policy/index.test.d.ts.map +0 -1
- package/dist/lib/policy/index.test.js +0 -328
- package/dist/lib/policy/index.test.js.map +0 -1
- package/dist/lib/policy/types.d.ts +0 -27
- package/dist/lib/policy/types.d.ts.map +0 -1
- package/dist/lib/policy/types.js +0 -2
- package/dist/lib/policy/types.js.map +0 -1
- package/dist/lib/pubsub/index.d.ts +0 -23
- package/dist/lib/pubsub/index.d.ts.map +0 -1
- package/dist/lib/pubsub/index.js +0 -55
- package/dist/lib/pubsub/index.js.map +0 -1
- package/dist/lib/pubsub/index.test.d.ts +0 -2
- package/dist/lib/pubsub/index.test.d.ts.map +0 -1
- package/dist/lib/pubsub/index.test.js +0 -550
- package/dist/lib/pubsub/index.test.js.map +0 -1
- package/dist/lib/pubsub/types.d.ts +0 -7
- package/dist/lib/pubsub/types.d.ts.map +0 -1
- package/dist/lib/pubsub/types.js +0 -2
- package/dist/lib/pubsub/types.js.map +0 -1
- package/dist/lib/queue/index.d.ts +0 -28
- package/dist/lib/queue/index.d.ts.map +0 -1
- package/dist/lib/queue/index.js +0 -211
- package/dist/lib/queue/index.js.map +0 -1
- package/dist/lib/queue/index.test.d.ts +0 -2
- package/dist/lib/queue/index.test.d.ts.map +0 -1
- package/dist/lib/queue/index.test.js +0 -740
- package/dist/lib/queue/index.test.js.map +0 -1
- package/dist/lib/queue/types.d.ts +0 -52
- package/dist/lib/queue/types.d.ts.map +0 -1
- package/dist/lib/queue/types.js +0 -2
- package/dist/lib/queue/types.js.map +0 -1
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_helpers = require("../../policy/helpers.cjs");
|
|
3
|
+
//#region src/lib/policy/index.ts
|
|
4
|
+
var Policy = class {
|
|
5
|
+
rules = [];
|
|
6
|
+
allow(params) {
|
|
7
|
+
const actions = this.toActions(params.action);
|
|
8
|
+
for (const action of actions) this.rules.push({
|
|
9
|
+
action,
|
|
10
|
+
conditions: params.conditions,
|
|
11
|
+
inverted: false,
|
|
12
|
+
reason: params.reason
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
forbid(params) {
|
|
16
|
+
const actions = this.toActions(params.action);
|
|
17
|
+
for (const action of actions) this.rules.push({
|
|
18
|
+
action,
|
|
19
|
+
conditions: params.conditions,
|
|
20
|
+
inverted: true,
|
|
21
|
+
reason: params.reason
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
toActions(action) {
|
|
25
|
+
if (Array.isArray(action)) return action;
|
|
26
|
+
return [action];
|
|
27
|
+
}
|
|
28
|
+
can(action, object) {
|
|
29
|
+
const filteredRules = this.rules.filter((rule) => rule.action === action);
|
|
30
|
+
const forbidResult = this.checkForbids(filteredRules, object);
|
|
31
|
+
if (forbidResult) return forbidResult;
|
|
32
|
+
const allowResult = this.checkAllows(filteredRules, object);
|
|
33
|
+
if (allowResult) return allowResult;
|
|
34
|
+
return {
|
|
35
|
+
allowed: false,
|
|
36
|
+
reason: void 0
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
checkForbids(rules, object) {
|
|
40
|
+
for (const rule of rules) {
|
|
41
|
+
if (!rule.inverted) continue;
|
|
42
|
+
if (!rule.conditions || Object.entries(rule.conditions).length === 0) return {
|
|
43
|
+
allowed: false,
|
|
44
|
+
reason: rule.reason
|
|
45
|
+
};
|
|
46
|
+
if (object && this.deepMatch(object, rule.conditions)) return {
|
|
47
|
+
allowed: false,
|
|
48
|
+
reason: rule.reason
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
checkAllows(rules, object) {
|
|
53
|
+
for (const rule of rules) {
|
|
54
|
+
if (rule.inverted) continue;
|
|
55
|
+
if (!rule.conditions || Object.entries(rule.conditions).length === 0) return {
|
|
56
|
+
allowed: true,
|
|
57
|
+
reason: rule.reason
|
|
58
|
+
};
|
|
59
|
+
if (object && this.deepMatch(object, rule.conditions)) return {
|
|
60
|
+
allowed: true,
|
|
61
|
+
reason: rule.reason
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
deepMatch(objectValue, conditionValue) {
|
|
66
|
+
if (typeof objectValue !== "object" || objectValue === null) return false;
|
|
67
|
+
for (const [key, nestedCondition] of Object.entries(conditionValue)) {
|
|
68
|
+
const nestedValue = Reflect.get(objectValue, key);
|
|
69
|
+
if (!this.matchValue(nestedValue, nestedCondition)) return false;
|
|
70
|
+
}
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
matchValue(actual, condition) {
|
|
74
|
+
if (typeof condition !== "object" || condition === null) return false;
|
|
75
|
+
if ("fn" in condition && typeof condition.fn === "function") return condition.fn(actual);
|
|
76
|
+
return this.deepMatch(actual, condition);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
//#endregion
|
|
80
|
+
exports.Policy = Policy;
|
|
81
|
+
exports.and = require_helpers.and;
|
|
82
|
+
exports.endsWith = require_helpers.endsWith;
|
|
83
|
+
exports.eq = require_helpers.eq;
|
|
84
|
+
exports.gt = require_helpers.gt;
|
|
85
|
+
exports.gte = require_helpers.gte;
|
|
86
|
+
exports.has = require_helpers.has;
|
|
87
|
+
exports.hasAny = require_helpers.hasAny;
|
|
88
|
+
exports.hasLength = require_helpers.hasLength;
|
|
89
|
+
exports.includes = require_helpers.includes;
|
|
90
|
+
exports.isDefined = require_helpers.isDefined;
|
|
91
|
+
exports.isEmpty = require_helpers.isEmpty;
|
|
92
|
+
exports.isNullish = require_helpers.isNullish;
|
|
93
|
+
exports.lt = require_helpers.lt;
|
|
94
|
+
exports.lte = require_helpers.lte;
|
|
95
|
+
exports.matches = require_helpers.matches;
|
|
96
|
+
exports.neq = require_helpers.neq;
|
|
97
|
+
exports.not = require_helpers.not;
|
|
98
|
+
exports.or = require_helpers.or;
|
|
99
|
+
exports.startsWith = require_helpers.startsWith;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ConditionHelper, and, endsWith, eq, gt, gte, has, hasAny, hasLength, includes, isDefined, isEmpty, isNullish, lt, lte, matches, neq, not, or, startsWith } from "../../policy/helpers.cjs";
|
|
2
|
+
import { Action, AllowParams, ForbidParams } from "../../policy/types.cjs";
|
|
3
|
+
|
|
4
|
+
//#region src/lib/policy/index.d.ts
|
|
5
|
+
declare class Policy<TEntity extends Record<string, unknown> = Record<string, unknown>> {
|
|
6
|
+
private rules;
|
|
7
|
+
allow(params: AllowParams<TEntity>): void;
|
|
8
|
+
forbid(params: ForbidParams<TEntity>): void;
|
|
9
|
+
private toActions;
|
|
10
|
+
can(action: Action, object?: TEntity): {
|
|
11
|
+
allowed: boolean;
|
|
12
|
+
reason: string | undefined;
|
|
13
|
+
};
|
|
14
|
+
private checkForbids;
|
|
15
|
+
private checkAllows;
|
|
16
|
+
private deepMatch;
|
|
17
|
+
private matchValue;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { type ConditionHelper, Policy, and, endsWith, eq, gt, gte, has, hasAny, hasLength, includes, isDefined, isEmpty, isNullish, lt, lte, matches, neq, not, or, startsWith };
|
|
21
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../../../src/lib/policy/index.ts"],"mappings":";;;;cAEa,MAAA,iBACK,MAAA,oBAA0B,MAAA;EAAA,QAElC,KAAA;EAED,KAAA,CAAM,MAAA,EAAQ,WAAA,CAAY,OAAA;EAa1B,MAAA,CAAO,MAAA,EAAQ,YAAA,CAAa,OAAA;EAAA,QAa3B,SAAA;EAQD,GAAA,CAAI,MAAA,EAAQ,MAAA,EAAQ,MAAA,GAAS,OAAA;;;;UAkB5B,YAAA;EAAA,QAgBA,WAAA;EAAA,QAgBA,SAAA;EAAA,QAgBA,UAAA;AAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ConditionHelper, and, endsWith, eq, gt, gte, has, hasAny, hasLength, includes, isDefined, isEmpty, isNullish, lt, lte, matches, neq, not, or, startsWith } from "../../policy/helpers.mjs";
|
|
2
|
+
import { Action, AllowParams, ForbidParams } from "../../policy/types.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/lib/policy/index.d.ts
|
|
5
|
+
declare class Policy<TEntity extends Record<string, unknown> = Record<string, unknown>> {
|
|
6
|
+
private rules;
|
|
7
|
+
allow(params: AllowParams<TEntity>): void;
|
|
8
|
+
forbid(params: ForbidParams<TEntity>): void;
|
|
9
|
+
private toActions;
|
|
10
|
+
can(action: Action, object?: TEntity): {
|
|
11
|
+
allowed: boolean;
|
|
12
|
+
reason: string | undefined;
|
|
13
|
+
};
|
|
14
|
+
private checkForbids;
|
|
15
|
+
private checkAllows;
|
|
16
|
+
private deepMatch;
|
|
17
|
+
private matchValue;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { type ConditionHelper, Policy, and, endsWith, eq, gt, gte, has, hasAny, hasLength, includes, isDefined, isEmpty, isNullish, lt, lte, matches, neq, not, or, startsWith };
|
|
21
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/lib/policy/index.ts"],"mappings":";;;;cAEa,MAAA,iBACK,MAAA,oBAA0B,MAAA;EAAA,QAElC,KAAA;EAED,KAAA,CAAM,MAAA,EAAQ,WAAA,CAAY,OAAA;EAa1B,MAAA,CAAO,MAAA,EAAQ,YAAA,CAAa,OAAA;EAAA,QAa3B,SAAA;EAQD,GAAA,CAAI,MAAA,EAAQ,MAAA,EAAQ,MAAA,GAAS,OAAA;;;;UAkB5B,YAAA;EAAA,QAgBA,WAAA;EAAA,QAgBA,SAAA;EAAA,QAgBA,UAAA;AAAA"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { and, endsWith, eq, gt, gte, has, hasAny, hasLength, includes, isDefined, isEmpty, isNullish, lt, lte, matches, neq, not, or, startsWith } from "../../policy/helpers.mjs";
|
|
2
|
+
//#region src/lib/policy/index.ts
|
|
3
|
+
var Policy = class {
|
|
4
|
+
rules = [];
|
|
5
|
+
allow(params) {
|
|
6
|
+
const actions = this.toActions(params.action);
|
|
7
|
+
for (const action of actions) this.rules.push({
|
|
8
|
+
action,
|
|
9
|
+
conditions: params.conditions,
|
|
10
|
+
inverted: false,
|
|
11
|
+
reason: params.reason
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
forbid(params) {
|
|
15
|
+
const actions = this.toActions(params.action);
|
|
16
|
+
for (const action of actions) this.rules.push({
|
|
17
|
+
action,
|
|
18
|
+
conditions: params.conditions,
|
|
19
|
+
inverted: true,
|
|
20
|
+
reason: params.reason
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
toActions(action) {
|
|
24
|
+
if (Array.isArray(action)) return action;
|
|
25
|
+
return [action];
|
|
26
|
+
}
|
|
27
|
+
can(action, object) {
|
|
28
|
+
const filteredRules = this.rules.filter((rule) => rule.action === action);
|
|
29
|
+
const forbidResult = this.checkForbids(filteredRules, object);
|
|
30
|
+
if (forbidResult) return forbidResult;
|
|
31
|
+
const allowResult = this.checkAllows(filteredRules, object);
|
|
32
|
+
if (allowResult) return allowResult;
|
|
33
|
+
return {
|
|
34
|
+
allowed: false,
|
|
35
|
+
reason: void 0
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
checkForbids(rules, object) {
|
|
39
|
+
for (const rule of rules) {
|
|
40
|
+
if (!rule.inverted) continue;
|
|
41
|
+
if (!rule.conditions || Object.entries(rule.conditions).length === 0) return {
|
|
42
|
+
allowed: false,
|
|
43
|
+
reason: rule.reason
|
|
44
|
+
};
|
|
45
|
+
if (object && this.deepMatch(object, rule.conditions)) return {
|
|
46
|
+
allowed: false,
|
|
47
|
+
reason: rule.reason
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
checkAllows(rules, object) {
|
|
52
|
+
for (const rule of rules) {
|
|
53
|
+
if (rule.inverted) continue;
|
|
54
|
+
if (!rule.conditions || Object.entries(rule.conditions).length === 0) return {
|
|
55
|
+
allowed: true,
|
|
56
|
+
reason: rule.reason
|
|
57
|
+
};
|
|
58
|
+
if (object && this.deepMatch(object, rule.conditions)) return {
|
|
59
|
+
allowed: true,
|
|
60
|
+
reason: rule.reason
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
deepMatch(objectValue, conditionValue) {
|
|
65
|
+
if (typeof objectValue !== "object" || objectValue === null) return false;
|
|
66
|
+
for (const [key, nestedCondition] of Object.entries(conditionValue)) {
|
|
67
|
+
const nestedValue = Reflect.get(objectValue, key);
|
|
68
|
+
if (!this.matchValue(nestedValue, nestedCondition)) return false;
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
matchValue(actual, condition) {
|
|
73
|
+
if (typeof condition !== "object" || condition === null) return false;
|
|
74
|
+
if ("fn" in condition && typeof condition.fn === "function") return condition.fn(actual);
|
|
75
|
+
return this.deepMatch(actual, condition);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
//#endregion
|
|
79
|
+
export { Policy, and, endsWith, eq, gt, gte, has, hasAny, hasLength, includes, isDefined, isEmpty, isNullish, lt, lte, matches, neq, not, or, startsWith };
|
|
80
|
+
|
|
81
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/lib/policy/index.ts"],"sourcesContent":["import type { Action, AllowParams, ForbidParams, Rule } from \"./types.js\";\n\nexport class Policy<\n TEntity extends Record<string, unknown> = Record<string, unknown>,\n> {\n private rules: Rule<TEntity>[] = [];\n\n public allow(params: AllowParams<TEntity>) {\n const actions = this.toActions(params.action);\n\n for (const action of actions) {\n this.rules.push({\n action,\n conditions: params.conditions,\n inverted: false,\n reason: params.reason,\n });\n }\n }\n\n public forbid(params: ForbidParams<TEntity>) {\n const actions = this.toActions(params.action);\n\n for (const action of actions) {\n this.rules.push({\n action,\n conditions: params.conditions,\n inverted: true,\n reason: params.reason,\n });\n }\n }\n\n private toActions(action: Action | Action[]) {\n if (Array.isArray(action)) {\n return action;\n }\n\n return [action];\n }\n\n public can(action: Action, object?: TEntity) {\n const filteredRules = this.rules.filter((rule) => rule.action === action);\n\n const forbidResult = this.checkForbids(filteredRules, object);\n\n if (forbidResult) {\n return forbidResult;\n }\n\n const allowResult = this.checkAllows(filteredRules, object);\n\n if (allowResult) {\n return allowResult;\n }\n\n return { allowed: false, reason: undefined };\n }\n\n private checkForbids(rules: Rule<TEntity>[], object?: TEntity) {\n for (const rule of rules) {\n if (!rule.inverted) {\n continue;\n }\n\n if (!rule.conditions || Object.entries(rule.conditions).length === 0) {\n return { allowed: false, reason: rule.reason };\n }\n\n if (object && this.deepMatch(object, rule.conditions)) {\n return { allowed: false, reason: rule.reason };\n }\n }\n }\n\n private checkAllows(rules: Rule<TEntity>[], object?: TEntity) {\n for (const rule of rules) {\n if (rule.inverted) {\n continue;\n }\n\n if (!rule.conditions || Object.entries(rule.conditions).length === 0) {\n return { allowed: true, reason: rule.reason };\n }\n\n if (object && this.deepMatch(object, rule.conditions)) {\n return { allowed: true, reason: rule.reason };\n }\n }\n }\n\n private deepMatch(objectValue: unknown, conditionValue: object) {\n if (typeof objectValue !== \"object\" || objectValue === null) {\n return false;\n }\n\n for (const [key, nestedCondition] of Object.entries(conditionValue)) {\n const nestedValue = Reflect.get(objectValue, key);\n\n if (!this.matchValue(nestedValue, nestedCondition)) {\n return false;\n }\n }\n\n return true;\n }\n\n private matchValue(actual: unknown, condition: unknown) {\n if (typeof condition !== \"object\" || condition === null) {\n return false;\n }\n\n if (\"fn\" in condition && typeof condition.fn === \"function\") {\n return condition.fn(actual);\n }\n\n return this.deepMatch(actual, condition);\n }\n}\n\nexport type { ConditionHelper } from \"./helpers.js\";\nexport {\n and,\n endsWith,\n eq,\n gt,\n gte,\n has,\n hasAny,\n hasLength,\n includes,\n isDefined,\n isEmpty,\n isNullish,\n lt,\n lte,\n matches,\n neq,\n not,\n or,\n startsWith,\n} from \"./helpers.js\";\n"],"mappings":";;AAEA,IAAa,SAAb,MAEE;CACA,QAAiC,EAAE;CAEnC,MAAa,QAA8B;EACzC,MAAM,UAAU,KAAK,UAAU,OAAO,OAAO;AAE7C,OAAK,MAAM,UAAU,QACnB,MAAK,MAAM,KAAK;GACd;GACA,YAAY,OAAO;GACnB,UAAU;GACV,QAAQ,OAAO;GAChB,CAAC;;CAIN,OAAc,QAA+B;EAC3C,MAAM,UAAU,KAAK,UAAU,OAAO,OAAO;AAE7C,OAAK,MAAM,UAAU,QACnB,MAAK,MAAM,KAAK;GACd;GACA,YAAY,OAAO;GACnB,UAAU;GACV,QAAQ,OAAO;GAChB,CAAC;;CAIN,UAAkB,QAA2B;AAC3C,MAAI,MAAM,QAAQ,OAAO,CACvB,QAAO;AAGT,SAAO,CAAC,OAAO;;CAGjB,IAAW,QAAgB,QAAkB;EAC3C,MAAM,gBAAgB,KAAK,MAAM,QAAQ,SAAS,KAAK,WAAW,OAAO;EAEzE,MAAM,eAAe,KAAK,aAAa,eAAe,OAAO;AAE7D,MAAI,aACF,QAAO;EAGT,MAAM,cAAc,KAAK,YAAY,eAAe,OAAO;AAE3D,MAAI,YACF,QAAO;AAGT,SAAO;GAAE,SAAS;GAAO,QAAQ,KAAA;GAAW;;CAG9C,aAAqB,OAAwB,QAAkB;AAC7D,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,CAAC,KAAK,SACR;AAGF,OAAI,CAAC,KAAK,cAAc,OAAO,QAAQ,KAAK,WAAW,CAAC,WAAW,EACjE,QAAO;IAAE,SAAS;IAAO,QAAQ,KAAK;IAAQ;AAGhD,OAAI,UAAU,KAAK,UAAU,QAAQ,KAAK,WAAW,CACnD,QAAO;IAAE,SAAS;IAAO,QAAQ,KAAK;IAAQ;;;CAKpD,YAAoB,OAAwB,QAAkB;AAC5D,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,KAAK,SACP;AAGF,OAAI,CAAC,KAAK,cAAc,OAAO,QAAQ,KAAK,WAAW,CAAC,WAAW,EACjE,QAAO;IAAE,SAAS;IAAM,QAAQ,KAAK;IAAQ;AAG/C,OAAI,UAAU,KAAK,UAAU,QAAQ,KAAK,WAAW,CACnD,QAAO;IAAE,SAAS;IAAM,QAAQ,KAAK;IAAQ;;;CAKnD,UAAkB,aAAsB,gBAAwB;AAC9D,MAAI,OAAO,gBAAgB,YAAY,gBAAgB,KACrD,QAAO;AAGT,OAAK,MAAM,CAAC,KAAK,oBAAoB,OAAO,QAAQ,eAAe,EAAE;GACnE,MAAM,cAAc,QAAQ,IAAI,aAAa,IAAI;AAEjD,OAAI,CAAC,KAAK,WAAW,aAAa,gBAAgB,CAChD,QAAO;;AAIX,SAAO;;CAGT,WAAmB,QAAiB,WAAoB;AACtD,MAAI,OAAO,cAAc,YAAY,cAAc,KACjD,QAAO;AAGT,MAAI,QAAQ,aAAa,OAAO,UAAU,OAAO,WAC/C,QAAO,UAAU,GAAG,OAAO;AAG7B,SAAO,KAAK,UAAU,QAAQ,UAAU"}
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_runtime = require("../../prompts/core/runtime.cjs");
|
|
3
|
+
const require_session = require("../../prompts/core/session.cjs");
|
|
4
|
+
let node_util = require("node:util");
|
|
5
|
+
//#region src/lib/prompts/index.ts
|
|
6
|
+
const pointer = (active) => {
|
|
7
|
+
return active ? paint("cyan", "❯") : " ";
|
|
8
|
+
};
|
|
9
|
+
const addErrorLine = (content, errorMessage) => {
|
|
10
|
+
if (!errorMessage) return content;
|
|
11
|
+
return `${content}\n${errorMark()} ${paint("red", errorMessage)}`;
|
|
12
|
+
};
|
|
13
|
+
const insertAt = (value, at, character) => {
|
|
14
|
+
return `${value.slice(0, at)}${character}${value.slice(at)}`;
|
|
15
|
+
};
|
|
16
|
+
const INVERSE = "\x1B[7m";
|
|
17
|
+
const RESET = "\x1B[0m";
|
|
18
|
+
const WHITESPACE = /\s/;
|
|
19
|
+
const NUMBER_CHAR = /[0-9.-]/;
|
|
20
|
+
const CURSOR_BLOCK = `${INVERSE} ${RESET}`;
|
|
21
|
+
const paint = (color, text) => {
|
|
22
|
+
return (0, node_util.styleText)(color, text, { validateStream: false });
|
|
23
|
+
};
|
|
24
|
+
const questionMark = () => paint("cyan", "?");
|
|
25
|
+
const successMark = () => paint("green", "✔");
|
|
26
|
+
const errorMark = () => paint("red", "✖");
|
|
27
|
+
const renderQuestionLine = (message, content) => {
|
|
28
|
+
return `${questionMark()} ${paint("cyan", message)} ${content}`;
|
|
29
|
+
};
|
|
30
|
+
const renderSuccessLine = (message, content) => {
|
|
31
|
+
return `${successMark()} ${message} ${content}`;
|
|
32
|
+
};
|
|
33
|
+
const createTextState = (value) => {
|
|
34
|
+
return {
|
|
35
|
+
value,
|
|
36
|
+
cursor: value.length,
|
|
37
|
+
selectionAnchor: null
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
const submitTextValue = (state, options) => {
|
|
41
|
+
const value = state.value.length > 0 ? state.value : options.defaultValue ?? "";
|
|
42
|
+
if (options.required && value.trim().length === 0) return { errorMessage: options.requiredMessage ?? "A value is required" };
|
|
43
|
+
return { value };
|
|
44
|
+
};
|
|
45
|
+
const getSelectionRange = (state) => {
|
|
46
|
+
if (state.selectionAnchor === null || state.selectionAnchor === state.cursor) return null;
|
|
47
|
+
return {
|
|
48
|
+
start: Math.min(state.selectionAnchor, state.cursor),
|
|
49
|
+
end: Math.max(state.selectionAnchor, state.cursor)
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
const moveCursor = (state, cursor, keepSelection) => {
|
|
53
|
+
if (!keepSelection) return {
|
|
54
|
+
...state,
|
|
55
|
+
cursor,
|
|
56
|
+
selectionAnchor: null
|
|
57
|
+
};
|
|
58
|
+
return {
|
|
59
|
+
...state,
|
|
60
|
+
cursor,
|
|
61
|
+
selectionAnchor: state.selectionAnchor ?? state.cursor
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
const deleteRange = (state, start, end) => {
|
|
65
|
+
return {
|
|
66
|
+
value: `${state.value.slice(0, start)}${state.value.slice(end)}`,
|
|
67
|
+
cursor: start,
|
|
68
|
+
selectionAnchor: null
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
const deleteSelectedRange = (state) => {
|
|
72
|
+
const selection = getSelectionRange(state);
|
|
73
|
+
if (!selection) return state;
|
|
74
|
+
return deleteRange(state, selection.start, selection.end);
|
|
75
|
+
};
|
|
76
|
+
const findWordStart = (value, cursor) => {
|
|
77
|
+
let index = cursor;
|
|
78
|
+
while (index > 0 && WHITESPACE.test(value[index - 1] ?? "")) index -= 1;
|
|
79
|
+
while (index > 0 && !WHITESPACE.test(value[index - 1] ?? "")) index -= 1;
|
|
80
|
+
return index;
|
|
81
|
+
};
|
|
82
|
+
const findWordEnd = (value, cursor) => {
|
|
83
|
+
let index = cursor;
|
|
84
|
+
while (index < value.length && WHITESPACE.test(value[index] ?? "")) index += 1;
|
|
85
|
+
while (index < value.length && !WHITESPACE.test(value[index] ?? "")) index += 1;
|
|
86
|
+
return index;
|
|
87
|
+
};
|
|
88
|
+
const renderTextSelection = (state, mask) => {
|
|
89
|
+
const selection = getSelectionRange(state);
|
|
90
|
+
const content = mask ? mask.repeat(state.value.length) : state.value;
|
|
91
|
+
const boundedCursor = Math.max(0, Math.min(state.cursor, content.length));
|
|
92
|
+
if (!selection) {
|
|
93
|
+
if (content.length === 0) return CURSOR_BLOCK;
|
|
94
|
+
if (boundedCursor === content.length) return `${content}${CURSOR_BLOCK}`;
|
|
95
|
+
const focusedChar = content[boundedCursor] ?? " ";
|
|
96
|
+
return `${content.slice(0, boundedCursor)}${INVERSE}${focusedChar}${RESET}${content.slice(boundedCursor + 1)}`;
|
|
97
|
+
}
|
|
98
|
+
const selected = content.slice(selection.start, selection.end);
|
|
99
|
+
return `${content.slice(0, selection.start)}${INVERSE}${selected}${RESET}${content.slice(selection.end)}`;
|
|
100
|
+
};
|
|
101
|
+
const textOnKey = (state, key) => {
|
|
102
|
+
switch (key.name) {
|
|
103
|
+
case "ctrl_a": return {
|
|
104
|
+
...state,
|
|
105
|
+
cursor: state.value.length,
|
|
106
|
+
selectionAnchor: 0
|
|
107
|
+
};
|
|
108
|
+
case "home": return moveCursor(state, 0, false);
|
|
109
|
+
case "end": return moveCursor(state, state.value.length, false);
|
|
110
|
+
case "shift_ctrl_left": return moveCursor(state, findWordStart(state.value, state.cursor), true);
|
|
111
|
+
case "shift_ctrl_right": return moveCursor(state, findWordEnd(state.value, state.cursor), true);
|
|
112
|
+
case "left": return moveCursor(state, Math.max(state.cursor - 1, 0), false);
|
|
113
|
+
case "shift_left": return moveCursor(state, Math.max(state.cursor - 1, 0), true);
|
|
114
|
+
case "right": return moveCursor(state, Math.min(state.cursor + 1, state.value.length), false);
|
|
115
|
+
case "ctrl_left": return moveCursor(state, findWordStart(state.value, state.cursor), false);
|
|
116
|
+
case "ctrl_right": return moveCursor(state, findWordEnd(state.value, state.cursor), false);
|
|
117
|
+
case "shift_right": return moveCursor(state, Math.min(state.cursor + 1, state.value.length), true);
|
|
118
|
+
case "backspace": {
|
|
119
|
+
const selectionDeleted = deleteSelectedRange(state);
|
|
120
|
+
if (selectionDeleted !== state) return selectionDeleted;
|
|
121
|
+
if (state.cursor === 0) return state;
|
|
122
|
+
const nextCursor = state.cursor - 1;
|
|
123
|
+
return {
|
|
124
|
+
value: `${state.value.slice(0, nextCursor)}${state.value.slice(state.cursor)}`,
|
|
125
|
+
cursor: nextCursor,
|
|
126
|
+
selectionAnchor: null
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
case "ctrl_backspace": {
|
|
130
|
+
const selectionDeleted = deleteSelectedRange(state);
|
|
131
|
+
if (selectionDeleted !== state) return selectionDeleted;
|
|
132
|
+
if (state.cursor === 0) return state;
|
|
133
|
+
return deleteRange(state, findWordStart(state.value, state.cursor), state.cursor);
|
|
134
|
+
}
|
|
135
|
+
case "delete": {
|
|
136
|
+
const selectionDeleted = deleteSelectedRange(state);
|
|
137
|
+
if (selectionDeleted !== state) return selectionDeleted;
|
|
138
|
+
return {
|
|
139
|
+
...state,
|
|
140
|
+
value: `${state.value.slice(0, state.cursor)}${state.value.slice(state.cursor + 1)}`
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
case "character":
|
|
144
|
+
case "space": {
|
|
145
|
+
const collapsed = deleteSelectedRange(state);
|
|
146
|
+
const text = key.name === "space" ? " " : key.value ?? "";
|
|
147
|
+
return {
|
|
148
|
+
value: insertAt(collapsed.value, collapsed.cursor, text),
|
|
149
|
+
cursor: collapsed.cursor + 1,
|
|
150
|
+
selectionAnchor: null
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
default: return state;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
const input = async (options, runtime) => {
|
|
157
|
+
return require_session.runPromptSession({
|
|
158
|
+
runtime: runtime ?? require_runtime.createNodePromptRuntime(),
|
|
159
|
+
options,
|
|
160
|
+
initialState: createTextState(options.defaultValue ?? ""),
|
|
161
|
+
render: ({ options: currentOptions, state, errorMessage }) => {
|
|
162
|
+
let text = renderTextSelection(state);
|
|
163
|
+
if (state.value.length === 0 && currentOptions.placeholder) text = `${CURSOR_BLOCK}${paint("dim", currentOptions.placeholder)}`;
|
|
164
|
+
return addErrorLine(renderQuestionLine(currentOptions.message, text), errorMessage);
|
|
165
|
+
},
|
|
166
|
+
complete: ({ options: currentOptions, value }) => {
|
|
167
|
+
return renderSuccessLine(currentOptions.message, value);
|
|
168
|
+
},
|
|
169
|
+
onKey: (state, key) => {
|
|
170
|
+
return textOnKey(state, key);
|
|
171
|
+
},
|
|
172
|
+
onSubmit: (state) => submitTextValue(state, options)
|
|
173
|
+
});
|
|
174
|
+
};
|
|
175
|
+
const password = async (options, runtime) => {
|
|
176
|
+
const promptRuntime = runtime ?? require_runtime.createNodePromptRuntime();
|
|
177
|
+
const initialValue = options.defaultValue ?? "";
|
|
178
|
+
const mask = options.mask;
|
|
179
|
+
return require_session.runPromptSession({
|
|
180
|
+
runtime: promptRuntime,
|
|
181
|
+
options,
|
|
182
|
+
initialState: createTextState(initialValue),
|
|
183
|
+
render: ({ options: currentOptions, state, errorMessage }) => {
|
|
184
|
+
let visible;
|
|
185
|
+
if (state.value.length === 0 && currentOptions.placeholder) visible = `${CURSOR_BLOCK}${paint("dim", currentOptions.placeholder)}`;
|
|
186
|
+
else if (mask !== void 0) visible = renderTextSelection(state, mask);
|
|
187
|
+
else visible = CURSOR_BLOCK;
|
|
188
|
+
return addErrorLine(renderQuestionLine(currentOptions.message, visible), errorMessage);
|
|
189
|
+
},
|
|
190
|
+
complete: ({ options: currentOptions, value }) => {
|
|
191
|
+
return renderSuccessLine(currentOptions.message, mask !== void 0 ? mask.repeat(value.length) : "");
|
|
192
|
+
},
|
|
193
|
+
onKey: (state, key) => {
|
|
194
|
+
return textOnKey(state, key);
|
|
195
|
+
},
|
|
196
|
+
onSubmit: (state) => submitTextValue(state, options)
|
|
197
|
+
});
|
|
198
|
+
};
|
|
199
|
+
const confirm = async (options, runtime) => {
|
|
200
|
+
return require_session.runPromptSession({
|
|
201
|
+
runtime: runtime ?? require_runtime.createNodePromptRuntime(),
|
|
202
|
+
options,
|
|
203
|
+
initialState: { value: options.defaultValue ?? false },
|
|
204
|
+
render: ({ options: currentOptions, state, errorMessage }) => {
|
|
205
|
+
const yesLabel = currentOptions.activeLabel ?? "Yes";
|
|
206
|
+
const noLabel = currentOptions.inactiveLabel ?? "No";
|
|
207
|
+
const rendered = state.value ? yesLabel : noLabel;
|
|
208
|
+
return addErrorLine([renderQuestionLine(currentOptions.message, `(${rendered})`), paint("dim", " (y/n to select, ← yes / → no, space to toggle)")].join("\n"), errorMessage);
|
|
209
|
+
},
|
|
210
|
+
complete: ({ options: currentOptions, value }) => {
|
|
211
|
+
const label = value ? currentOptions.activeLabel ?? "Yes" : currentOptions.inactiveLabel ?? "No";
|
|
212
|
+
return renderSuccessLine(currentOptions.message, label);
|
|
213
|
+
},
|
|
214
|
+
onKey: (state, key) => {
|
|
215
|
+
switch (key.name) {
|
|
216
|
+
case "left": return { value: true };
|
|
217
|
+
case "right": return { value: false };
|
|
218
|
+
case "space": return { value: !state.value };
|
|
219
|
+
case "character": {
|
|
220
|
+
const lowered = (key.value ?? "").toLowerCase();
|
|
221
|
+
if (lowered === "y") return { value: true };
|
|
222
|
+
if (lowered === "n") return { value: false };
|
|
223
|
+
return state;
|
|
224
|
+
}
|
|
225
|
+
default: return state;
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
onSubmit: (state) => {
|
|
229
|
+
return { value: state.value };
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
};
|
|
233
|
+
const number = async (options, runtime) => {
|
|
234
|
+
return require_session.runPromptSession({
|
|
235
|
+
runtime: runtime ?? require_runtime.createNodePromptRuntime(),
|
|
236
|
+
options,
|
|
237
|
+
initialState: createTextState(options.defaultValue === void 0 ? "" : String(options.defaultValue)),
|
|
238
|
+
render: ({ options: currentOptions, state, errorMessage }) => {
|
|
239
|
+
return addErrorLine(renderQuestionLine(currentOptions.message, renderTextSelection(state)), errorMessage);
|
|
240
|
+
},
|
|
241
|
+
complete: ({ options: currentOptions, value }) => {
|
|
242
|
+
return renderSuccessLine(currentOptions.message, String(value));
|
|
243
|
+
},
|
|
244
|
+
onKey: (state, key) => {
|
|
245
|
+
const next = textOnKey(state, key);
|
|
246
|
+
if (!(key.name === "character" || key.name === "space")) return next;
|
|
247
|
+
const value = key.name === "space" ? " " : key.value ?? "";
|
|
248
|
+
if (!NUMBER_CHAR.test(value)) return state;
|
|
249
|
+
if (value === "." || value === "-") {
|
|
250
|
+
const collapsed = deleteSelectedRange(state);
|
|
251
|
+
if (value === "." && collapsed.value.includes(".")) return state;
|
|
252
|
+
if (value === "-") {
|
|
253
|
+
if (collapsed.cursor !== 0) return state;
|
|
254
|
+
if (collapsed.value.includes("-")) return state;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return next;
|
|
258
|
+
},
|
|
259
|
+
onSubmit: (state) => {
|
|
260
|
+
const raw = state.value.trim();
|
|
261
|
+
if (raw.length === 0) return { errorMessage: options.requiredMessage ?? "A number is required" };
|
|
262
|
+
const parsed = Number(raw);
|
|
263
|
+
if (!Number.isFinite(parsed)) return { errorMessage: options.invalidMessage ?? "Please enter a valid number" };
|
|
264
|
+
if (options.min !== void 0 && parsed < options.min) return { errorMessage: options.minMessage ?? `Number must be greater than or equal to ${options.min}` };
|
|
265
|
+
if (options.max !== void 0 && parsed > options.max) return { errorMessage: options.maxMessage ?? `Number must be lower than or equal to ${options.max}` };
|
|
266
|
+
return { value: parsed };
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
};
|
|
270
|
+
const findFirstEnabledIndex = (choices) => {
|
|
271
|
+
const firstEnabledIndex = choices.findIndex((choice) => !choice.disabled);
|
|
272
|
+
if (firstEnabledIndex >= 0) return firstEnabledIndex;
|
|
273
|
+
return 0;
|
|
274
|
+
};
|
|
275
|
+
const findNextEnabledIndex = (choices, cursor, direction) => {
|
|
276
|
+
const total = choices.length;
|
|
277
|
+
let currentCursor = cursor;
|
|
278
|
+
for (let offset = 0; offset < total; offset++) {
|
|
279
|
+
const nextCursor = (currentCursor + direction + total) % total;
|
|
280
|
+
const nextChoice = choices[nextCursor];
|
|
281
|
+
if (nextChoice && !nextChoice.disabled) return nextCursor;
|
|
282
|
+
currentCursor = nextCursor;
|
|
283
|
+
}
|
|
284
|
+
return currentCursor;
|
|
285
|
+
};
|
|
286
|
+
const findDefaultIndex = (choices, defaultValue) => {
|
|
287
|
+
if (defaultValue === void 0) return findFirstEnabledIndex(choices);
|
|
288
|
+
const index = choices.findIndex((choice) => choice.value === defaultValue && !choice.disabled);
|
|
289
|
+
if (index >= 0) return index;
|
|
290
|
+
return findFirstEnabledIndex(choices);
|
|
291
|
+
};
|
|
292
|
+
const select = async (options, runtime) => {
|
|
293
|
+
return require_session.runPromptSession({
|
|
294
|
+
runtime: runtime ?? require_runtime.createNodePromptRuntime(),
|
|
295
|
+
options,
|
|
296
|
+
initialState: { cursor: findDefaultIndex(options.choices, options.defaultValue) },
|
|
297
|
+
render: ({ options: currentOptions, state, errorMessage }) => {
|
|
298
|
+
const lines = [renderQuestionLine(currentOptions.message, "")];
|
|
299
|
+
for (let index = 0; index < currentOptions.choices.length; index++) {
|
|
300
|
+
const choice = currentOptions.choices[index];
|
|
301
|
+
if (!choice) continue;
|
|
302
|
+
const active = state.cursor === index;
|
|
303
|
+
const label = choice.label ?? choice.value;
|
|
304
|
+
const hint = choice.hint ? paint("dim", ` (${choice.hint})`) : "";
|
|
305
|
+
const disabled = choice.disabled ? paint("yellow", " [disabled]") : "";
|
|
306
|
+
lines.push(`${pointer(active)} ${label}${hint}${disabled}`);
|
|
307
|
+
}
|
|
308
|
+
return addErrorLine(lines.join("\n"), errorMessage);
|
|
309
|
+
},
|
|
310
|
+
complete: ({ options: currentOptions, value }) => {
|
|
311
|
+
const selected = currentOptions.choices.find((choice) => choice.value === value);
|
|
312
|
+
return renderSuccessLine(currentOptions.message, selected?.label ?? value);
|
|
313
|
+
},
|
|
314
|
+
onKey: (state, key) => {
|
|
315
|
+
switch (key.name) {
|
|
316
|
+
case "up": return { cursor: findNextEnabledIndex(options.choices, state.cursor, -1) };
|
|
317
|
+
case "down": return { cursor: findNextEnabledIndex(options.choices, state.cursor, 1) };
|
|
318
|
+
default: return state;
|
|
319
|
+
}
|
|
320
|
+
},
|
|
321
|
+
onSubmit: (state) => {
|
|
322
|
+
const selectedChoice = options.choices[state.cursor];
|
|
323
|
+
if (!selectedChoice) return { errorMessage: "Please select an option" };
|
|
324
|
+
if (selectedChoice.disabled) return { errorMessage: "Selected option is disabled" };
|
|
325
|
+
return { value: selectedChoice.value };
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
};
|
|
329
|
+
const multiselect = async (options, runtime) => {
|
|
330
|
+
return require_session.runPromptSession({
|
|
331
|
+
runtime: runtime ?? require_runtime.createNodePromptRuntime(),
|
|
332
|
+
options,
|
|
333
|
+
initialState: {
|
|
334
|
+
cursor: findFirstEnabledIndex(options.choices),
|
|
335
|
+
selected: new Set(options.defaultValue ?? [])
|
|
336
|
+
},
|
|
337
|
+
render: ({ options: currentOptions, state, errorMessage }) => {
|
|
338
|
+
const lines = [renderQuestionLine(currentOptions.message, "")];
|
|
339
|
+
for (let index = 0; index < currentOptions.choices.length; index++) {
|
|
340
|
+
const choice = currentOptions.choices[index];
|
|
341
|
+
if (!choice) continue;
|
|
342
|
+
const active = state.cursor === index;
|
|
343
|
+
const checked = state.selected.has(choice.value) ? "◉" : "◯";
|
|
344
|
+
const disabled = choice.disabled ? paint("yellow", " [disabled]") : "";
|
|
345
|
+
const label = choice.label ?? choice.value;
|
|
346
|
+
const hint = choice.hint ? paint("dim", ` (${choice.hint})`) : "";
|
|
347
|
+
lines.push(`${pointer(active)} ${checked} ${label}${hint}${disabled}`);
|
|
348
|
+
}
|
|
349
|
+
lines.push(paint("dim", " (space to toggle, a to toggle all, enter to submit)"));
|
|
350
|
+
return addErrorLine(lines.join("\n"), errorMessage);
|
|
351
|
+
},
|
|
352
|
+
complete: ({ options: currentOptions, value }) => {
|
|
353
|
+
const labelMap = new Map(currentOptions.choices.map((choice) => [choice.value, choice.label]));
|
|
354
|
+
const labels = value.map((v) => labelMap.get(v) ?? v);
|
|
355
|
+
return renderSuccessLine(currentOptions.message, labels.join(", "));
|
|
356
|
+
},
|
|
357
|
+
onKey: (state, key) => {
|
|
358
|
+
switch (key.name) {
|
|
359
|
+
case "up": return {
|
|
360
|
+
...state,
|
|
361
|
+
cursor: findNextEnabledIndex(options.choices, state.cursor, -1)
|
|
362
|
+
};
|
|
363
|
+
case "down": return {
|
|
364
|
+
...state,
|
|
365
|
+
cursor: findNextEnabledIndex(options.choices, state.cursor, 1)
|
|
366
|
+
};
|
|
367
|
+
case "character":
|
|
368
|
+
if ((key.value ?? "").toLowerCase() === "a") {
|
|
369
|
+
const enabledValues = options.choices.filter((choice) => !choice.disabled).map((choice) => choice.value);
|
|
370
|
+
if (!(enabledValues.length > 0)) return state;
|
|
371
|
+
const areAllEnabledSelected = enabledValues.every((value) => state.selected.has(value));
|
|
372
|
+
const nextSelection = new Set(state.selected);
|
|
373
|
+
if (areAllEnabledSelected) for (const value of enabledValues) nextSelection.delete(value);
|
|
374
|
+
else for (const value of enabledValues) nextSelection.add(value);
|
|
375
|
+
return {
|
|
376
|
+
...state,
|
|
377
|
+
selected: nextSelection
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
return state;
|
|
381
|
+
case "space": {
|
|
382
|
+
const currentChoice = options.choices[state.cursor];
|
|
383
|
+
if (!currentChoice || currentChoice.disabled) return state;
|
|
384
|
+
const nextSelection = new Set(state.selected);
|
|
385
|
+
if (nextSelection.has(currentChoice.value)) nextSelection.delete(currentChoice.value);
|
|
386
|
+
else nextSelection.add(currentChoice.value);
|
|
387
|
+
return {
|
|
388
|
+
...state,
|
|
389
|
+
selected: nextSelection
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
default: return state;
|
|
393
|
+
}
|
|
394
|
+
},
|
|
395
|
+
onSubmit: (state) => {
|
|
396
|
+
const values = options.choices.filter((choice) => state.selected.has(choice.value)).map((choice) => choice.value);
|
|
397
|
+
if (options.min !== void 0 && values.length < options.min) return { errorMessage: `Please select at least ${options.min} options` };
|
|
398
|
+
if (options.max !== void 0 && values.length > options.max) return { errorMessage: `Please select at most ${options.max} options` };
|
|
399
|
+
return { value: values };
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
};
|
|
403
|
+
//#endregion
|
|
404
|
+
exports.confirm = confirm;
|
|
405
|
+
exports.input = input;
|
|
406
|
+
exports.multiselect = multiselect;
|
|
407
|
+
exports.number = number;
|
|
408
|
+
exports.password = password;
|
|
409
|
+
exports.select = select;
|