@dereekb/dbx-cli 14.1.0 → 14.3.0
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/eslint/index.esm.js +0 -195
- package/eslint/package.json +4 -3
- package/firebase-api-manifest/main.js +124 -13
- package/firebase-api-manifest/package.json +4 -3
- package/firestore-indexes/src/model-firebase-index-schema.d.ts +4 -4
- package/firestore-query-manifest/main.js +4 -3
- package/firestore-query-manifest/package.json +4 -3
- package/generate-firestore-indexes/main.js +3 -2
- package/generate-firestore-indexes/package.json +3 -2
- package/generate-mcp-manifest/package.json +4 -3
- package/generate-route-manifest/package.json +3 -2
- package/index.esm.js +4228 -1344
- package/lint-cache/package.json +3 -2
- package/manifest-extract/index.esm.js +113 -7
- package/manifest-extract/package.json +8 -8
- package/manifest-extract/src/lib/types.d.ts +10 -0
- package/model-test/package.json +2 -2
- package/package.json +6 -6
- package/route/package.json +7 -7
- package/src/lib/auth/index.d.ts +1 -0
- package/src/lib/auth/oidc.loopback.d.ts +127 -0
- package/src/lib/cache/cache.command.factory.d.ts +44 -0
- package/src/lib/cache/data-cache.codec.d.ts +36 -0
- package/src/lib/cache/data-cache.d.ts +272 -0
- package/src/lib/cache/data-cache.fingerprint.d.ts +109 -0
- package/src/lib/cache/data-cache.options.d.ts +98 -0
- package/src/lib/cache/index.d.ts +5 -0
- package/src/lib/config/env.d.ts +43 -7
- package/src/lib/config/env.resolve.d.ts +4 -3
- package/src/lib/config/paths.d.ts +11 -1
- package/src/lib/firestore/firestore-query.command.d.ts +25 -1
- package/src/lib/index.d.ts +1 -0
- package/src/lib/runner/run.d.ts +11 -0
- package/src/lib/util/browser.d.ts +23 -0
- package/src/lib/util/index.d.ts +1 -0
- package/src/lib/util/interactive.d.ts +10 -1
- package/test/package.json +10 -9
- package/validate/package.json +3 -3
package/lint-cache/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/dbx-cli-lint-cache",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.3.0",
|
|
4
|
+
"sideEffects": false,
|
|
4
5
|
"private": true,
|
|
5
6
|
"type": "module",
|
|
6
7
|
"devDependencies": {
|
|
@@ -8,7 +9,7 @@
|
|
|
8
9
|
"eslint": "10.9.1"
|
|
9
10
|
},
|
|
10
11
|
"peerDependencies": {
|
|
11
|
-
"@dereekb/util": "14.
|
|
12
|
+
"@dereekb/util": "14.3.0",
|
|
12
13
|
"yargs": "^18.0.0"
|
|
13
14
|
}
|
|
14
15
|
}
|
|
@@ -696,6 +696,10 @@ var MCP_TOOL_NAME_SEGMENT_TAG = 'dbxModelMcpToolNameSegment';
|
|
|
696
696
|
var MODEL_TYPE_VALUE_PATTERN = /^[a-z][A-Za-z0-9_$]*$/;
|
|
697
697
|
var TOOL_NAME_SEGMENT_PATTERN = /^[A-Za-z][A-Za-z0-9_$]*$/;
|
|
698
698
|
var IDENTITY_FN = 'firestoreModelIdentity';
|
|
699
|
+
// the declared-type counterparts of IDENTITY_FN, which is all a .d.ts retains of the call
|
|
700
|
+
var IDENTITY_TYPE = 'FirestoreModelIdentity';
|
|
701
|
+
var ROOT_IDENTITY_TYPE = 'RootFirestoreModelIdentity';
|
|
702
|
+
var IDENTITY_WITH_PARENT_TYPE = 'FirestoreModelIdentityWithParent';
|
|
699
703
|
var SINGLE_ITEM_COLLECTION_FN = 'singleItemFirestoreCollection';
|
|
700
704
|
var ROOT_SINGLE_ITEM_COLLECTION_FN = 'rootSingleItemFirestoreCollection';
|
|
701
705
|
var SINGLE_ITEM_COLLECTION_FN_NAMES = [
|
|
@@ -763,13 +767,25 @@ function readIdentities(sourceFile) {
|
|
|
763
767
|
for(var _iterator1 = statement.getDeclarations()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
764
768
|
var decl = _step1.value;
|
|
765
769
|
var initializer = decl.getInitializer();
|
|
766
|
-
if (
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
770
|
+
if (initializer && Node.isCallExpression(initializer)) {
|
|
771
|
+
if (initializer.getExpression().getText() !== IDENTITY_FN) continue;
|
|
772
|
+
var parsed = parseFirestoreModelIdentityArgs(initializer.getArguments());
|
|
773
|
+
if (parsed) {
|
|
774
|
+
out.push(_object_spread_props(_object_spread({
|
|
775
|
+
identityConst: decl.getName()
|
|
776
|
+
}, parsed), {
|
|
777
|
+
parentModelType: undefined
|
|
778
|
+
}));
|
|
779
|
+
}
|
|
780
|
+
} else {
|
|
781
|
+
// A declaration file has no initializer to read — the identity survives only in the declared
|
|
782
|
+
// type, which is the whole reason a node_modules-installed package can contribute models at all.
|
|
783
|
+
var parsed1 = parseDeclaredIdentityType(decl.getTypeNode());
|
|
784
|
+
if (parsed1) {
|
|
785
|
+
out.push(_object_spread({
|
|
786
|
+
identityConst: decl.getName()
|
|
787
|
+
}, parsed1));
|
|
788
|
+
}
|
|
773
789
|
}
|
|
774
790
|
}
|
|
775
791
|
} catch (err) {
|
|
@@ -803,6 +819,96 @@ function readIdentities(sourceFile) {
|
|
|
803
819
|
}
|
|
804
820
|
return out;
|
|
805
821
|
}
|
|
822
|
+
/**
|
|
823
|
+
* Reads an identity out of the DECLARED TYPE of an initializer-less export.
|
|
824
|
+
*
|
|
825
|
+
* The three shapes `@dereekb/firebase` declares, after a `.d.ts` rewrites every import as an inline
|
|
826
|
+
* `import("…").` qualifier:
|
|
827
|
+
*
|
|
828
|
+
* - `RootFirestoreModelIdentity<"worker", "wk">`
|
|
829
|
+
* - `FirestoreModelIdentity<"worker", "wk">`
|
|
830
|
+
* - `FirestoreModelIdentityWithParent<RootFirestoreModelIdentity<"prompt", "orp">, "version", "orpv">`
|
|
831
|
+
*
|
|
832
|
+
* @param typeNode - The declared type node, when the declaration carries one.
|
|
833
|
+
* @returns The identity parts, or undefined when the type is not one of the identity shapes.
|
|
834
|
+
*/ function parseDeclaredIdentityType(typeNode) {
|
|
835
|
+
var result;
|
|
836
|
+
var named = readNamedTypeNode(typeNode);
|
|
837
|
+
if (named) {
|
|
838
|
+
var typeName = named.typeName, args = named.args;
|
|
839
|
+
if (typeName === IDENTITY_WITH_PARENT_TYPE && args.length >= 3) {
|
|
840
|
+
var _readLiteralTypeText;
|
|
841
|
+
var parent = parseDeclaredIdentityType(args[0]);
|
|
842
|
+
result = {
|
|
843
|
+
modelType: (_readLiteralTypeText = readLiteralTypeText(args[1])) !== null && _readLiteralTypeText !== void 0 ? _readLiteralTypeText : '',
|
|
844
|
+
collectionPrefix: readLiteralTypeText(args[2]),
|
|
845
|
+
parentIdentityConst: undefined,
|
|
846
|
+
parentModelType: parent === null || parent === void 0 ? void 0 : parent.modelType
|
|
847
|
+
};
|
|
848
|
+
} else if ((typeName === ROOT_IDENTITY_TYPE || typeName === IDENTITY_TYPE) && args.length >= 2) {
|
|
849
|
+
var _readLiteralTypeText1;
|
|
850
|
+
result = {
|
|
851
|
+
modelType: (_readLiteralTypeText1 = readLiteralTypeText(args[0])) !== null && _readLiteralTypeText1 !== void 0 ? _readLiteralTypeText1 : '',
|
|
852
|
+
collectionPrefix: readLiteralTypeText(args[1]),
|
|
853
|
+
parentIdentityConst: undefined,
|
|
854
|
+
parentModelType: undefined
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
// a default-parameterized identity carries no literals, so it names no model
|
|
858
|
+
if (result && !result.modelType) {
|
|
859
|
+
result = undefined;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
return result;
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* Normalizes a type node to its name and type arguments.
|
|
866
|
+
*
|
|
867
|
+
* Two shapes, because a `.d.ts` does not write the one the source did: source that imported the type
|
|
868
|
+
* normally leaves a `TypeReference` (`RootFirestoreModelIdentity<…>`), while a declaration file inlines
|
|
869
|
+
* the import and leaves an `ImportType` (`import("@dereekb/firebase").RootFirestoreModelIdentity<…>`),
|
|
870
|
+
* whose name is its QUALIFIER rather than its type name. Reading only the first is what made a
|
|
871
|
+
* declaration-sourced identity invisible.
|
|
872
|
+
*
|
|
873
|
+
* @param typeNode - The type node to read.
|
|
874
|
+
* @returns The unqualified type name and its type arguments, or undefined when the node is neither shape.
|
|
875
|
+
*/ function readNamedTypeNode(typeNode) {
|
|
876
|
+
var result;
|
|
877
|
+
if (typeNode) {
|
|
878
|
+
if (Node.isImportTypeNode(typeNode)) {
|
|
879
|
+
var qualifier = typeNode.getQualifier();
|
|
880
|
+
if (qualifier) {
|
|
881
|
+
var _qualifier_getText_split_pop;
|
|
882
|
+
result = {
|
|
883
|
+
typeName: (_qualifier_getText_split_pop = qualifier.getText().split('.').pop()) !== null && _qualifier_getText_split_pop !== void 0 ? _qualifier_getText_split_pop : '',
|
|
884
|
+
args: typeNode.getTypeArguments()
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
} else if (Node.isTypeReference(typeNode)) {
|
|
888
|
+
var _typeNode_getTypeName_getText_split_pop;
|
|
889
|
+
result = {
|
|
890
|
+
typeName: (_typeNode_getTypeName_getText_split_pop = typeNode.getTypeName().getText().split('.').pop()) !== null && _typeNode_getTypeName_getText_split_pop !== void 0 ? _typeNode_getTypeName_getText_split_pop : '',
|
|
891
|
+
args: typeNode.getTypeArguments()
|
|
892
|
+
};
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
return result;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Reads the text of a string-literal type node (`"wk"` → `wk`).
|
|
899
|
+
*
|
|
900
|
+
* @param node - The type node to read.
|
|
901
|
+
* @returns The literal's text, or undefined when the node is not a string literal type.
|
|
902
|
+
*/ function readLiteralTypeText(node) {
|
|
903
|
+
var result;
|
|
904
|
+
if (node && Node.isLiteralTypeNode(node)) {
|
|
905
|
+
var literal = node.getLiteral();
|
|
906
|
+
if (Node.isStringLiteral(literal)) {
|
|
907
|
+
result = literal.getLiteralText();
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
return result;
|
|
911
|
+
}
|
|
806
912
|
function readInterfaces(sourceFile) {
|
|
807
913
|
var out = [];
|
|
808
914
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/dbx-cli/manifest-extract",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"@dereekb/date": "14.
|
|
8
|
-
"@dereekb/dbx-cli": "14.
|
|
9
|
-
"@dereekb/firebase": "14.
|
|
10
|
-
"@dereekb/model": "14.
|
|
11
|
-
"@dereekb/nestjs": "14.
|
|
12
|
-
"@dereekb/rxjs": "14.
|
|
13
|
-
"@dereekb/util": "14.
|
|
7
|
+
"@dereekb/date": "14.3.0",
|
|
8
|
+
"@dereekb/dbx-cli": "14.3.0",
|
|
9
|
+
"@dereekb/firebase": "14.3.0",
|
|
10
|
+
"@dereekb/model": "14.3.0",
|
|
11
|
+
"@dereekb/nestjs": "14.3.0",
|
|
12
|
+
"@dereekb/rxjs": "14.3.0",
|
|
13
|
+
"@dereekb/util": "14.3.0",
|
|
14
14
|
"ts-morph": "^28.0.0"
|
|
15
15
|
},
|
|
16
16
|
"exports": {
|
|
@@ -119,6 +119,16 @@ export interface ModelExtractionIdentity {
|
|
|
119
119
|
readonly modelType: string;
|
|
120
120
|
readonly collectionPrefix: string | undefined;
|
|
121
121
|
readonly parentIdentityConst: string | undefined;
|
|
122
|
+
/**
|
|
123
|
+
* Model type of the parent, when the identity was read from a DECLARATION rather than a call.
|
|
124
|
+
*
|
|
125
|
+
* A `.d.ts` spells the parent as an inline type (`FirestoreModelIdentityWithParent<
|
|
126
|
+
* RootFirestoreModelIdentity<"openRouterPrompt", "orp">, …>`) rather than by naming the const the
|
|
127
|
+
* source called `firestoreModelIdentity` with, so the const name the parent chain is walked by is not
|
|
128
|
+
* present to read. The model type is, and it identifies the same parent — the orchestrator resolves
|
|
129
|
+
* one to the other against the global identity registry.
|
|
130
|
+
*/
|
|
131
|
+
readonly parentModelType: string | undefined;
|
|
122
132
|
}
|
|
123
133
|
/**
|
|
124
134
|
* One property on a `@dbxModel`-tagged interface.
|
package/model-test/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/dbx-cli/model-test",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"@dereekb/util": "14.
|
|
7
|
+
"@dereekb/util": "14.3.0",
|
|
8
8
|
"ts-morph": "^28.0.0"
|
|
9
9
|
},
|
|
10
10
|
"exports": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/dbx-cli",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"bin": {
|
|
@@ -66,11 +66,11 @@
|
|
|
66
66
|
}
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"@dereekb/date": "14.
|
|
70
|
-
"@dereekb/firebase": "14.
|
|
71
|
-
"@dereekb/model": "14.
|
|
72
|
-
"@dereekb/nestjs": "14.
|
|
73
|
-
"@dereekb/util": "14.
|
|
69
|
+
"@dereekb/date": "14.3.0",
|
|
70
|
+
"@dereekb/firebase": "14.3.0",
|
|
71
|
+
"@dereekb/model": "14.3.0",
|
|
72
|
+
"@dereekb/nestjs": "14.3.0",
|
|
73
|
+
"@dereekb/util": "14.3.0",
|
|
74
74
|
"@nestjs/common": "^12.0.1",
|
|
75
75
|
"arktype": "^2.2.0",
|
|
76
76
|
"firebase": "^12.18.0",
|
package/route/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/dbx-cli/route",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"@dereekb/date": "14.
|
|
8
|
-
"@dereekb/dbx-cli": "14.
|
|
9
|
-
"@dereekb/firebase": "14.
|
|
10
|
-
"@dereekb/model": "14.
|
|
11
|
-
"@dereekb/nestjs": "14.
|
|
12
|
-
"@dereekb/util": "14.
|
|
7
|
+
"@dereekb/date": "14.3.0",
|
|
8
|
+
"@dereekb/dbx-cli": "14.3.0",
|
|
9
|
+
"@dereekb/firebase": "14.3.0",
|
|
10
|
+
"@dereekb/model": "14.3.0",
|
|
11
|
+
"@dereekb/nestjs": "14.3.0",
|
|
12
|
+
"@dereekb/util": "14.3.0"
|
|
13
13
|
},
|
|
14
14
|
"exports": {
|
|
15
15
|
"./package.json": "./package.json",
|
package/src/lib/auth/index.d.ts
CHANGED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { type Maybe, type PortNumber, type WebsiteUrl } from '@dereekb/util';
|
|
2
|
+
/**
|
|
3
|
+
* Hostnames RFC 8252 §7.3 treats as the loopback interface, and the exact set `oidc-provider`
|
|
4
|
+
* recognizes as a loopback redirect host.
|
|
5
|
+
*
|
|
6
|
+
* `[::1]` carries its brackets because that is what `URL.hostname` returns for an IPv6 literal —
|
|
7
|
+
* the brackets are stripped again before the address is handed to `server.listen`.
|
|
8
|
+
*/
|
|
9
|
+
export declare const LOOPBACK_REDIRECT_HOSTNAMES: readonly string[];
|
|
10
|
+
/**
|
|
11
|
+
* The loopback port the CLI suggests when the configured redirect URI has no bindable port.
|
|
12
|
+
*
|
|
13
|
+
* Deliberately outside the 9900-9910 block the Firebase emulators occupy, so a suggested redirect
|
|
14
|
+
* URI never collides with a running emulator.
|
|
15
|
+
*/
|
|
16
|
+
export declare const SUGGESTED_CLI_LOOPBACK_REDIRECT_PORT: PortNumber;
|
|
17
|
+
/**
|
|
18
|
+
* Error code raised when the loopback listener cannot bind the redirect URI's port (e.g. the port
|
|
19
|
+
* is already in use, or is privileged).
|
|
20
|
+
*/
|
|
21
|
+
export declare const LOOPBACK_REDIRECT_LISTEN_FAILED_ERROR_CODE = "AUTH_REDIRECT_LISTEN_FAILED";
|
|
22
|
+
/**
|
|
23
|
+
* Error code raised when no redirect reached the loopback listener within the allotted time.
|
|
24
|
+
*/
|
|
25
|
+
export declare const LOOPBACK_REDIRECT_TIMEOUT_ERROR_CODE = "AUTH_REDIRECT_TIMEOUT";
|
|
26
|
+
/**
|
|
27
|
+
* A redirect URI the CLI can bind a local HTTP listener to, decomposed into its parts.
|
|
28
|
+
*/
|
|
29
|
+
export interface LoopbackRedirectTarget {
|
|
30
|
+
/**
|
|
31
|
+
* The normalized redirect URI to send as `redirect_uri`. Identical to the configured URI unless a
|
|
32
|
+
* port override was applied.
|
|
33
|
+
*/
|
|
34
|
+
readonly redirectUri: WebsiteUrl;
|
|
35
|
+
/**
|
|
36
|
+
* The loopback hostname, as `URL.hostname` reports it (so `[::1]` keeps its brackets).
|
|
37
|
+
*/
|
|
38
|
+
readonly hostname: string;
|
|
39
|
+
/**
|
|
40
|
+
* The port to bind. Always a positive integer — a `0`/absent port is not a capturable target.
|
|
41
|
+
*/
|
|
42
|
+
readonly port: PortNumber;
|
|
43
|
+
/**
|
|
44
|
+
* The path the provider redirects to. Requests to any other path are answered `404` so a stray
|
|
45
|
+
* `/favicon.ico` cannot be mistaken for the authorization redirect.
|
|
46
|
+
*/
|
|
47
|
+
readonly pathname: string;
|
|
48
|
+
}
|
|
49
|
+
export interface ParseLoopbackRedirectUriInput {
|
|
50
|
+
/**
|
|
51
|
+
* The configured redirect URI.
|
|
52
|
+
*/
|
|
53
|
+
readonly redirectUri: Maybe<string>;
|
|
54
|
+
/**
|
|
55
|
+
* Optional port override, replacing whatever port the redirect URI carries.
|
|
56
|
+
*
|
|
57
|
+
* The resulting URI is what gets sent as `redirect_uri`, so it must be registered with the OAuth
|
|
58
|
+
* client just like the configured one.
|
|
59
|
+
*/
|
|
60
|
+
readonly port?: Maybe<PortNumber>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Decomposes a redirect URI into a {@link LoopbackRedirectTarget} when the CLI can bind a local
|
|
64
|
+
* listener for it.
|
|
65
|
+
*
|
|
66
|
+
* A target is only produced for an `http:` loopback URI carrying a concrete, non-zero port. The
|
|
67
|
+
* conventional `http://127.0.0.1:0/callback` placeholder is deliberately NOT capturable: binding an
|
|
68
|
+
* ephemeral port would mean sending a `redirect_uri` that differs from the registered one, which
|
|
69
|
+
* every OAuth provider rejects unless the client is registered as a native app (where loopback
|
|
70
|
+
* ports are compared port-insensitively).
|
|
71
|
+
*
|
|
72
|
+
* @param input - The parse inputs.
|
|
73
|
+
* @param input.redirectUri - The configured redirect URI.
|
|
74
|
+
* @param input.port - Optional port override applied to the parsed URI.
|
|
75
|
+
* @returns The bindable target, or `undefined` when the URI cannot be captured locally.
|
|
76
|
+
* @__NO_SIDE_EFFECTS__
|
|
77
|
+
*/
|
|
78
|
+
export declare function parseLoopbackRedirectUri(input: ParseLoopbackRedirectUriInput): Maybe<LoopbackRedirectTarget>;
|
|
79
|
+
export interface StartLoopbackRedirectCaptureInput {
|
|
80
|
+
/**
|
|
81
|
+
* The bindable target, from {@link parseLoopbackRedirectUri}.
|
|
82
|
+
*/
|
|
83
|
+
readonly target: LoopbackRedirectTarget;
|
|
84
|
+
/**
|
|
85
|
+
* Text shown in the browser tab once the redirect is captured.
|
|
86
|
+
*/
|
|
87
|
+
readonly successMessage?: Maybe<string>;
|
|
88
|
+
}
|
|
89
|
+
export interface LoopbackRedirectCapture {
|
|
90
|
+
/**
|
|
91
|
+
* The `redirect_uri` the listener is bound to. Send this value in the authorization request.
|
|
92
|
+
*/
|
|
93
|
+
readonly redirectUri: WebsiteUrl;
|
|
94
|
+
/**
|
|
95
|
+
* The bound port.
|
|
96
|
+
*/
|
|
97
|
+
readonly port: PortNumber;
|
|
98
|
+
/**
|
|
99
|
+
* Resolves with the full redirect URL (query string included) the browser was sent to.
|
|
100
|
+
*
|
|
101
|
+
* A provider error redirect resolves rather than rejects — the returned URL carries the `error`
|
|
102
|
+
* params, which the shared redirect parser already turns into an `AUTH_PROVIDER_ERROR`.
|
|
103
|
+
*
|
|
104
|
+
* @param timeoutMs - Optional milliseconds to wait before rejecting with
|
|
105
|
+
* {@link LOOPBACK_REDIRECT_TIMEOUT_ERROR_CODE}. Waits indefinitely when omitted.
|
|
106
|
+
*/
|
|
107
|
+
readonly waitForRedirect: (timeoutMs?: Maybe<number>) => Promise<WebsiteUrl>;
|
|
108
|
+
/**
|
|
109
|
+
* Closes the listener and destroys any open sockets, so the CLI's event loop can drain.
|
|
110
|
+
*/
|
|
111
|
+
readonly close: () => Promise<void>;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Binds a local HTTP listener to a loopback redirect URI so the authorization code can be read
|
|
115
|
+
* straight out of the browser redirect instead of being pasted back by hand.
|
|
116
|
+
*
|
|
117
|
+
* The listener answers exactly one path — the redirect URI's own — and serves a short "you can close
|
|
118
|
+
* this tab" page. Everything else is answered `404`, which is what keeps the browser's automatic
|
|
119
|
+
* `/favicon.ico` request from being mistaken for the redirect.
|
|
120
|
+
*
|
|
121
|
+
* @param input - The capture inputs.
|
|
122
|
+
* @param input.target - The bindable target, from {@link parseLoopbackRedirectUri}.
|
|
123
|
+
* @param input.successMessage - Optional override for the browser success page's body line.
|
|
124
|
+
* @returns The started {@link LoopbackRedirectCapture}.
|
|
125
|
+
* @throws {CliError} `AUTH_REDIRECT_LISTEN_FAILED` when the port cannot be bound.
|
|
126
|
+
*/
|
|
127
|
+
export declare function startLoopbackRedirectCapture(input: StartLoopbackRedirectCaptureInput): Promise<LoopbackRedirectCapture>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type Maybe } from '@dereekb/util';
|
|
2
|
+
import type { CommandModule } from 'yargs';
|
|
3
|
+
import { type CliDataCache } from './data-cache';
|
|
4
|
+
/**
|
|
5
|
+
* Default command name for the data-cache management command.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DEFAULT_CLI_DATA_CACHE_COMMAND_NAME = "cache";
|
|
8
|
+
export interface CreateCacheCommandInput {
|
|
9
|
+
readonly cliName: string;
|
|
10
|
+
/**
|
|
11
|
+
* Override for the cache the command manages. Defaults to the CLI's own
|
|
12
|
+
* `<configDir>/cache` directory.
|
|
13
|
+
*/
|
|
14
|
+
readonly cache?: Maybe<CliDataCache>;
|
|
15
|
+
/**
|
|
16
|
+
* The current CLI build stamp. When supplied, `cache list` marks entries recorded by a different
|
|
17
|
+
* build, which is the one staleness signal the fingerprint deliberately does not cover.
|
|
18
|
+
*/
|
|
19
|
+
readonly cliBuildStamp?: Maybe<string>;
|
|
20
|
+
readonly commandName?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Factory for the `cache` command.
|
|
24
|
+
*
|
|
25
|
+
* Registered as a CONFIG command, not an API command: inspecting or clearing a LOCAL cache must work
|
|
26
|
+
* offline and without a token — which is precisely the situation in which a cache matters. Mirrors
|
|
27
|
+
* the `firestore-queries` (config) vs `firestore-query` (api) split.
|
|
28
|
+
*
|
|
29
|
+
* Subcommands:
|
|
30
|
+
* - `cache list [--env <env>] [--dataset <id>] [--json]`
|
|
31
|
+
* - `cache show <dataset> [--env <env>] [--fingerprint <fp>] [--data]`
|
|
32
|
+
* - `cache clear [--env <env>] [--dataset <id>] [--all]`
|
|
33
|
+
* - `cache prune --older-than <hours> [--env <env>] [--dataset <id>]`
|
|
34
|
+
*
|
|
35
|
+
* @param input - Factory configuration.
|
|
36
|
+
* @param input.cliName - The CLI's binary name, used to derive the default cache directory.
|
|
37
|
+
* @param input.cache - Optional cache override (tests point this at a temp dir).
|
|
38
|
+
* @param input.cliBuildStamp - The current build stamp, for marking entries from another build.
|
|
39
|
+
* @param input.commandName - Optional command-name override.
|
|
40
|
+
* @returns A yargs `CommandModule` for `runCli({ configCommands })`.
|
|
41
|
+
*
|
|
42
|
+
* @__NO_SIDE_EFFECTS__
|
|
43
|
+
*/
|
|
44
|
+
export declare function createCacheCommand(input: CreateCacheCommandInput): CommandModule;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error code thrown when a value handed to {@link toCliCacheJson} contains a reference cycle.
|
|
3
|
+
*/
|
|
4
|
+
export declare const CLI_DATA_CACHE_CYCLE_ERROR_CODE = "CLI_DATA_CACHE_CYCLE";
|
|
5
|
+
/**
|
|
6
|
+
* Error code thrown when a value handed to {@link toCliCacheJson} holds something that cannot be
|
|
7
|
+
* persisted and re-read at all — a function or a symbol.
|
|
8
|
+
*/
|
|
9
|
+
export declare const CLI_DATA_CACHE_UNSUPPORTED_VALUE_ERROR_CODE = "CLI_DATA_CACHE_UNSUPPORTED_VALUE";
|
|
10
|
+
/**
|
|
11
|
+
* Converts a value into a JSON-safe tree, tagging the types a plain `JSON.stringify` round trip
|
|
12
|
+
* would lose.
|
|
13
|
+
*
|
|
14
|
+
* This is a PRE-WALK rather than a `JSON.stringify` replacer, and that is load-bearing:
|
|
15
|
+
* `Date.prototype.toJSON` runs BEFORE a replacer sees the value, so a replacer is handed an ISO
|
|
16
|
+
* string and cannot tell a `Date` from a string that merely looks like one. Every model in a
|
|
17
|
+
* dbx-components app persists its dates through `firestoreDate` (an ISO string on the wire, a live
|
|
18
|
+
* `Date` in memory), so that distinction is the whole problem.
|
|
19
|
+
*
|
|
20
|
+
* Handled: `Date`, `Map`, `Set`, `undefined`, non-finite numbers, `bigint`, arrays, plain objects,
|
|
21
|
+
* and the JSON primitives. A class instance that is none of the above is FLATTENED to its own
|
|
22
|
+
* enumerable properties — the one lossy case, and the reason a stage whose output holds a class
|
|
23
|
+
* instance must supply its own codec.
|
|
24
|
+
*
|
|
25
|
+
* @param value - The value to encode.
|
|
26
|
+
* @returns A tree containing only values `JSON.stringify` renders losslessly.
|
|
27
|
+
* @throws {CliError} On a reference cycle, or on a function/symbol anywhere in the tree.
|
|
28
|
+
*/
|
|
29
|
+
export declare function toCliCacheJson(value: unknown): unknown;
|
|
30
|
+
/**
|
|
31
|
+
* Rebuilds a value encoded by {@link toCliCacheJson}, restoring the tagged types.
|
|
32
|
+
*
|
|
33
|
+
* @param raw - The JSON-parsed tree written by {@link toCliCacheJson}.
|
|
34
|
+
* @returns The decoded value.
|
|
35
|
+
*/
|
|
36
|
+
export declare function fromCliCacheJson(raw: unknown): unknown;
|