modality-ts 0.0.14 → 0.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/cli.js +108 -35
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/features/check/command.d.ts +2 -0
- package/dist/cli/features/check/command.d.ts.map +1 -1
- package/dist/cli/features/check/command.js +11 -3
- package/dist/cli/features/check/command.js.map +1 -1
- package/dist/cli/features/check/index.d.ts +2 -2
- package/dist/cli/features/check/index.d.ts.map +1 -1
- package/dist/cli/features/check/index.js +1 -1
- package/dist/cli/features/check/index.js.map +1 -1
- package/dist/cli/features/check/output.d.ts +22 -7
- package/dist/cli/features/check/output.d.ts.map +1 -1
- package/dist/cli/features/check/output.js +132 -76
- package/dist/cli/features/check/output.js.map +1 -1
- package/dist/cli/features/ci/command.d.ts +2 -0
- package/dist/cli/features/ci/command.d.ts.map +1 -1
- package/dist/cli/features/ci/command.js +21 -0
- package/dist/cli/features/ci/command.js.map +1 -1
- package/dist/cli/features/ci/index.d.ts +2 -0
- package/dist/cli/features/ci/index.d.ts.map +1 -1
- package/dist/cli/features/ci/index.js +1 -0
- package/dist/cli/features/ci/index.js.map +1 -1
- package/dist/cli/features/ci/output.d.ts +19 -0
- package/dist/cli/features/ci/output.d.ts.map +1 -0
- package/dist/cli/features/ci/output.js +40 -0
- package/dist/cli/features/ci/output.js.map +1 -0
- package/dist/cli/features/conform/index.d.ts +1 -0
- package/dist/cli/features/conform/index.d.ts.map +1 -1
- package/dist/cli/features/conform/index.js +1 -0
- package/dist/cli/features/conform/index.js.map +1 -1
- package/dist/cli/features/conform/output.d.ts +9 -0
- package/dist/cli/features/conform/output.d.ts.map +1 -0
- package/dist/cli/features/conform/output.js +28 -0
- package/dist/cli/features/conform/output.js.map +1 -0
- package/dist/cli/features/export/command.d.ts +2 -0
- package/dist/cli/features/export/command.d.ts.map +1 -1
- package/dist/cli/features/export/command.js +8 -2
- package/dist/cli/features/export/command.js.map +1 -1
- package/dist/cli/features/export/index.d.ts +1 -0
- package/dist/cli/features/export/index.d.ts.map +1 -1
- package/dist/cli/features/export/index.js +1 -0
- package/dist/cli/features/export/index.js.map +1 -1
- package/dist/cli/features/export/output.d.ts +8 -0
- package/dist/cli/features/export/output.d.ts.map +1 -0
- package/dist/cli/features/export/output.js +14 -0
- package/dist/cli/features/export/output.js.map +1 -0
- package/dist/cli/features/extract/command.d.ts +9 -0
- package/dist/cli/features/extract/command.d.ts.map +1 -1
- package/dist/cli/features/extract/command.js +20 -1
- package/dist/cli/features/extract/command.js.map +1 -1
- package/dist/cli/features/extract/index.d.ts +2 -0
- package/dist/cli/features/extract/index.d.ts.map +1 -1
- package/dist/cli/features/extract/index.js +1 -0
- package/dist/cli/features/extract/index.js.map +1 -1
- package/dist/cli/features/extract/output.d.ts +22 -0
- package/dist/cli/features/extract/output.d.ts.map +1 -0
- package/dist/cli/features/extract/output.js +48 -0
- package/dist/cli/features/extract/output.js.map +1 -0
- package/dist/cli/features/init/index.d.ts +1 -0
- package/dist/cli/features/init/index.d.ts.map +1 -1
- package/dist/cli/features/init/index.js +1 -0
- package/dist/cli/features/init/index.js.map +1 -1
- package/dist/cli/features/init/output.d.ts +4 -0
- package/dist/cli/features/init/output.d.ts.map +1 -0
- package/dist/cli/features/init/output.js +9 -0
- package/dist/cli/features/init/output.js.map +1 -0
- package/dist/cli/features/replay/index.d.ts +1 -0
- package/dist/cli/features/replay/index.d.ts.map +1 -1
- package/dist/cli/features/replay/index.js +1 -0
- package/dist/cli/features/replay/index.js.map +1 -1
- package/dist/cli/features/replay/output.d.ts +10 -0
- package/dist/cli/features/replay/output.d.ts.map +1 -0
- package/dist/cli/features/replay/output.js +37 -0
- package/dist/cli/features/replay/output.js.map +1 -0
- package/dist/cli/output.d.ts +28 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +64 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/extract/engine/ts/context.d.ts.map +1 -1
- package/dist/extract/engine/ts/context.js +7 -1
- package/dist/extract/engine/ts/context.js.map +1 -1
- package/dist/extract/engine/ts/react-source-transitions.d.ts +4 -1
- package/dist/extract/engine/ts/react-source-transitions.d.ts.map +1 -1
- package/dist/extract/engine/ts/react-source-transitions.js +11 -2
- package/dist/extract/engine/ts/react-source-transitions.js.map +1 -1
- package/dist/extract/engine/ts/transition/expressions.d.ts +1 -1
- package/dist/extract/engine/ts/transition/expressions.d.ts.map +1 -1
- package/dist/extract/engine/ts/transition/expressions.js +12 -1
- package/dist/extract/engine/ts/transition/expressions.js.map +1 -1
- package/dist/extract/engine/ts/transition/handlers.d.ts +3 -3
- package/dist/extract/engine/ts/transition/handlers.d.ts.map +1 -1
- package/dist/extract/engine/ts/transition/handlers.js +10 -7
- package/dist/extract/engine/ts/transition/handlers.js.map +1 -1
- package/dist/extract/engine/ts/transition/statement-summary.d.ts +6 -2
- package/dist/extract/engine/ts/transition/statement-summary.d.ts.map +1 -1
- package/dist/extract/engine/ts/transition/statement-summary.js +40 -6
- package/dist/extract/engine/ts/transition/statement-summary.js.map +1 -1
- package/dist/extract/engine/ts/types.d.ts +3 -0
- package/dist/extract/engine/ts/types.d.ts.map +1 -1
- package/dist/extract/sources/jotai/derived-writes.d.ts +11 -0
- package/dist/extract/sources/jotai/derived-writes.d.ts.map +1 -0
- package/dist/extract/sources/jotai/derived-writes.js +141 -0
- package/dist/extract/sources/jotai/derived-writes.js.map +1 -0
- package/dist/extract/sources/jotai/discover.d.ts +16 -0
- package/dist/extract/sources/jotai/discover.d.ts.map +1 -1
- package/dist/extract/sources/jotai/discover.js +163 -46
- package/dist/extract/sources/jotai/discover.js.map +1 -1
- package/dist/extract/sources/jotai/domains.d.ts +14 -1
- package/dist/extract/sources/jotai/domains.d.ts.map +1 -1
- package/dist/extract/sources/jotai/domains.js +481 -70
- package/dist/extract/sources/jotai/domains.js.map +1 -1
- package/dist/extract/sources/jotai/harness.d.ts +4 -1
- package/dist/extract/sources/jotai/harness.d.ts.map +1 -1
- package/dist/extract/sources/jotai/harness.js +10 -3
- package/dist/extract/sources/jotai/harness.js.map +1 -1
- package/dist/extract/sources/jotai/hydration.d.ts +16 -0
- package/dist/extract/sources/jotai/hydration.d.ts.map +1 -0
- package/dist/extract/sources/jotai/hydration.js +116 -0
- package/dist/extract/sources/jotai/hydration.js.map +1 -0
- package/dist/extract/sources/jotai/ids.d.ts +7 -0
- package/dist/extract/sources/jotai/ids.d.ts.map +1 -0
- package/dist/extract/sources/jotai/ids.js +23 -0
- package/dist/extract/sources/jotai/ids.js.map +1 -0
- package/dist/extract/sources/jotai/imports.d.ts +23 -0
- package/dist/extract/sources/jotai/imports.d.ts.map +1 -0
- package/dist/extract/sources/jotai/imports.js +111 -0
- package/dist/extract/sources/jotai/imports.js.map +1 -0
- package/dist/extract/sources/jotai/jsx.d.ts +4 -0
- package/dist/extract/sources/jotai/jsx.d.ts.map +1 -0
- package/dist/extract/sources/jotai/jsx.js +52 -0
- package/dist/extract/sources/jotai/jsx.js.map +1 -0
- package/dist/extract/sources/jotai/plugin.d.ts.map +1 -1
- package/dist/extract/sources/jotai/plugin.js +9 -2
- package/dist/extract/sources/jotai/plugin.js.map +1 -1
- package/dist/extract/sources/jotai/stores.d.ts +3 -0
- package/dist/extract/sources/jotai/stores.d.ts.map +1 -0
- package/dist/extract/sources/jotai/stores.js +40 -0
- package/dist/extract/sources/jotai/stores.js.map +1 -0
- package/dist/extract/sources/jotai/transitions.d.ts.map +1 -1
- package/dist/extract/sources/jotai/transitions.js +16 -5
- package/dist/extract/sources/jotai/transitions.js.map +1 -1
- package/dist/extract/sources/jotai/types.d.ts +22 -0
- package/dist/extract/sources/jotai/types.d.ts.map +1 -0
- package/dist/extract/sources/jotai/types.js +86 -0
- package/dist/extract/sources/jotai/types.js.map +1 -0
- package/dist/extract/sources/jotai/writes.d.ts +23 -1
- package/dist/extract/sources/jotai/writes.d.ts.map +1 -1
- package/dist/extract/sources/jotai/writes.js +330 -89
- package/dist/extract/sources/jotai/writes.js.map +1 -1
- package/dist/extract/sources/shared/react-transition-extract.d.ts +3 -0
- package/dist/extract/sources/shared/react-transition-extract.d.ts.map +1 -1
- package/dist/extract/sources/shared/react-transition-extract.js +5 -0
- package/dist/extract/sources/shared/react-transition-extract.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Value } from "modality-ts/core";
|
|
2
|
+
export type AtomConfigKind = "primitive" | "readOnlyDerived" | "readWriteDerived" | "writeOnlyDerived" | "storage" | "lazy" | "resettable" | "defaultResettable" | "refreshable" | "asyncWrapper" | "family" | "familyInstance";
|
|
3
|
+
export interface JotaiAtomMetadata {
|
|
4
|
+
atomName: string;
|
|
5
|
+
configKind: AtomConfigKind;
|
|
6
|
+
creator?: string;
|
|
7
|
+
storageKey?: string;
|
|
8
|
+
storageKind?: string;
|
|
9
|
+
getOnInit?: boolean;
|
|
10
|
+
resettableInitial?: Value;
|
|
11
|
+
readDependencies?: readonly string[];
|
|
12
|
+
familyFactory?: string;
|
|
13
|
+
familyParam?: string;
|
|
14
|
+
loadableState?: boolean;
|
|
15
|
+
asyncDerived?: boolean;
|
|
16
|
+
warning?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function metadataToRecord(metadata: JotaiAtomMetadata): Record<string, Value>;
|
|
19
|
+
export declare function metadataFromRecord(record: Record<string, Value> | undefined): JotaiAtomMetadata | undefined;
|
|
20
|
+
export declare function isResettableKind(kind: AtomConfigKind): boolean;
|
|
21
|
+
export declare function isWritableAtomKind(kind: AtomConfigKind): boolean;
|
|
22
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/extract/sources/jotai/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,MAAM,cAAc,GACtB,WAAW,GACX,iBAAiB,GACjB,kBAAkB,GAClB,kBAAkB,GAClB,SAAS,GACT,MAAM,GACN,YAAY,GACZ,mBAAmB,GACnB,aAAa,GACb,cAAc,GACd,QAAQ,GACR,gBAAgB,CAAC;AAErB,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iBAAiB,CAAC,EAAE,KAAK,CAAC;IAC1B,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,iBAAiB,GAC1B,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAqBvB;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,SAAS,GACxC,iBAAiB,GAAG,SAAS,CAqC/B;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAO9D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAWhE"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export function metadataToRecord(metadata) {
|
|
2
|
+
const record = {
|
|
3
|
+
atomName: metadata.atomName,
|
|
4
|
+
configKind: metadata.configKind,
|
|
5
|
+
};
|
|
6
|
+
if (metadata.creator)
|
|
7
|
+
record.creator = metadata.creator;
|
|
8
|
+
if (metadata.storageKey)
|
|
9
|
+
record.storageKey = metadata.storageKey;
|
|
10
|
+
if (metadata.storageKind)
|
|
11
|
+
record.storageKind = metadata.storageKind;
|
|
12
|
+
if (metadata.getOnInit !== undefined)
|
|
13
|
+
record.getOnInit = metadata.getOnInit;
|
|
14
|
+
if (metadata.resettableInitial !== undefined)
|
|
15
|
+
record.resettableInitial = metadata.resettableInitial;
|
|
16
|
+
if (metadata.readDependencies)
|
|
17
|
+
record.readDependencies = metadata.readDependencies.join(",");
|
|
18
|
+
if (metadata.familyFactory)
|
|
19
|
+
record.familyFactory = metadata.familyFactory;
|
|
20
|
+
if (metadata.familyParam)
|
|
21
|
+
record.familyParam = metadata.familyParam;
|
|
22
|
+
if (metadata.loadableState !== undefined)
|
|
23
|
+
record.loadableState = metadata.loadableState;
|
|
24
|
+
if (metadata.asyncDerived !== undefined)
|
|
25
|
+
record.asyncDerived = metadata.asyncDerived;
|
|
26
|
+
if (metadata.warning)
|
|
27
|
+
record.warning = metadata.warning;
|
|
28
|
+
return record;
|
|
29
|
+
}
|
|
30
|
+
export function metadataFromRecord(record) {
|
|
31
|
+
if (!record || typeof record.atomName !== "string")
|
|
32
|
+
return undefined;
|
|
33
|
+
const configKind = record.configKind;
|
|
34
|
+
if (typeof configKind !== "string")
|
|
35
|
+
return undefined;
|
|
36
|
+
return {
|
|
37
|
+
atomName: record.atomName,
|
|
38
|
+
configKind: configKind,
|
|
39
|
+
...(typeof record.creator === "string" ? { creator: record.creator } : {}),
|
|
40
|
+
...(typeof record.storageKey === "string"
|
|
41
|
+
? { storageKey: record.storageKey }
|
|
42
|
+
: {}),
|
|
43
|
+
...(typeof record.storageKind === "string"
|
|
44
|
+
? { storageKind: record.storageKind }
|
|
45
|
+
: {}),
|
|
46
|
+
...(typeof record.getOnInit === "boolean"
|
|
47
|
+
? { getOnInit: record.getOnInit }
|
|
48
|
+
: {}),
|
|
49
|
+
...(record.resettableInitial !== undefined
|
|
50
|
+
? { resettableInitial: record.resettableInitial }
|
|
51
|
+
: {}),
|
|
52
|
+
...(typeof record.readDependencies === "string"
|
|
53
|
+
? { readDependencies: record.readDependencies.split(",") }
|
|
54
|
+
: {}),
|
|
55
|
+
...(typeof record.familyFactory === "string"
|
|
56
|
+
? { familyFactory: record.familyFactory }
|
|
57
|
+
: {}),
|
|
58
|
+
...(typeof record.familyParam === "string"
|
|
59
|
+
? { familyParam: record.familyParam }
|
|
60
|
+
: {}),
|
|
61
|
+
...(typeof record.loadableState === "boolean"
|
|
62
|
+
? { loadableState: record.loadableState }
|
|
63
|
+
: {}),
|
|
64
|
+
...(typeof record.asyncDerived === "boolean"
|
|
65
|
+
? { asyncDerived: record.asyncDerived }
|
|
66
|
+
: {}),
|
|
67
|
+
...(typeof record.warning === "string" ? { warning: record.warning } : {}),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export function isResettableKind(kind) {
|
|
71
|
+
return (kind === "resettable" ||
|
|
72
|
+
kind === "defaultResettable" ||
|
|
73
|
+
kind === "storage" ||
|
|
74
|
+
kind === "refreshable");
|
|
75
|
+
}
|
|
76
|
+
export function isWritableAtomKind(kind) {
|
|
77
|
+
return (kind === "primitive" ||
|
|
78
|
+
kind === "readWriteDerived" ||
|
|
79
|
+
kind === "storage" ||
|
|
80
|
+
kind === "lazy" ||
|
|
81
|
+
kind === "resettable" ||
|
|
82
|
+
kind === "defaultResettable" ||
|
|
83
|
+
kind === "refreshable" ||
|
|
84
|
+
kind === "familyInstance");
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/extract/sources/jotai/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,30 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
1
2
|
import type { WriteChannel } from "modality-ts/extract/engine/spi";
|
|
2
|
-
import type { SourceAnchor } from "modality-ts/core";
|
|
3
|
+
import type { EffectIR, SourceAnchor, Value } from "modality-ts/core";
|
|
4
|
+
export interface JotaiWriteDiscovery {
|
|
5
|
+
channels: WriteChannel[];
|
|
6
|
+
warnings: {
|
|
7
|
+
message: string;
|
|
8
|
+
source?: SourceAnchor;
|
|
9
|
+
}[];
|
|
10
|
+
resetSymbol?: string;
|
|
11
|
+
resettableVarIds: Set<string>;
|
|
12
|
+
derivedWriteEffects: Map<string, EffectIR>;
|
|
13
|
+
setterFixedEffects: Map<string, EffectIR>;
|
|
14
|
+
storeScopedDecls: import("modality-ts/extract/engine/spi").SourceDecl[];
|
|
15
|
+
}
|
|
3
16
|
export declare function discoverJotaiSafetyWarnings(sourceText: string, fileName?: string): {
|
|
4
17
|
message: string;
|
|
5
18
|
source?: SourceAnchor;
|
|
6
19
|
}[];
|
|
7
20
|
export declare function discoverJotaiWriteChannels(sourceText: string, fileName?: string): WriteChannel[];
|
|
21
|
+
export declare function discoverJotaiWritesDetailed(sourceText: string, fileName?: string): JotaiWriteDiscovery;
|
|
22
|
+
export declare function setAtomImportNames(source: ts.SourceFile): {
|
|
23
|
+
useAtom: Set<string>;
|
|
24
|
+
useSetAtom: Set<string>;
|
|
25
|
+
};
|
|
26
|
+
export declare function getDefaultStoreImportNames(source: ts.SourceFile): Set<string>;
|
|
27
|
+
export declare function isUseAtomLikeCall(node: ts.Expression, names: Set<string>): node is ts.CallExpression;
|
|
28
|
+
export declare function jotaiResetSymbols(sourceText: string, fileName: string): Set<string>;
|
|
29
|
+
export declare function jotaiInitialByVarId(decls: readonly import("modality-ts/extract/engine/spi").SourceDecl[]): Map<string, Value>;
|
|
8
30
|
//# sourceMappingURL=writes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writes.d.ts","sourceRoot":"","sources":["../../../../src/extract/sources/jotai/writes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"writes.d.ts","sourceRoot":"","sources":["../../../../src/extract/sources/jotai/writes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAyBtE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,YAAY,CAAA;KAAE,EAAE,CAAC;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC3C,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1C,gBAAgB,EAAE,OAAO,gCAAgC,EAAE,UAAU,EAAE,CAAC;CACzE;AAED,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,EAClB,QAAQ,SAAa,GACpB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,YAAY,CAAA;CAAE,EAAE,CA2F9C;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,MAAM,EAClB,QAAQ,SAAa,GACpB,YAAY,EAAE,CAEhB;AAED,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,EAClB,QAAQ,SAAa,GACpB,mBAAmB,CAqQrB;AAqJD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,GAAG;IACzD,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACzB,CASA;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,CAO7E;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,EAAE,CAAC,UAAU,EACnB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GACjB,IAAI,IAAI,EAAE,CAAC,cAAc,CAM3B;AAED,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,GAAG,CAAC,MAAM,CAAC,CAab;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,OAAO,gCAAgC,EAAE,UAAU,EAAE,GACpE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAMpB"}
|
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
import * as ts from "typescript";
|
|
2
|
+
import { propertyName, componentNameFor } from "../../engine/ts/ast.js";
|
|
3
|
+
import { discoverComponentStoreScopes } from "./stores.js";
|
|
4
|
+
import { providerScopeFromJsx } from "./jsx.js";
|
|
5
|
+
import { discoverJotaiAtomsDetailed, duplicateAtomsForStore, } from "./discover.js";
|
|
6
|
+
import { hookImportedName, isHookCall, isJotaiModuleSpecifier, resolveJotaiImports, } from "./imports.js";
|
|
7
|
+
import { atomVarId, familyVarId } from "./ids.js";
|
|
8
|
+
import { discoverHydrationOverrides } from "./hydration.js";
|
|
9
|
+
import { isReadFunction, summarizeDerivedWriteBody } from "./derived-writes.js";
|
|
10
|
+
import { classifyAtomCall, staticFamilyParam, typeAliasDeclarations, } from "./domains.js";
|
|
11
|
+
import { isResettableKind, metadataFromRecord } from "./types.js";
|
|
12
|
+
import { atomCreatorName, isAtomCreatorCall } from "./imports.js";
|
|
2
13
|
export function discoverJotaiSafetyWarnings(sourceText, fileName = "state.ts") {
|
|
3
14
|
const source = ts.createSourceFile(fileName, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
|
15
|
+
const imports = resolveJotaiImports(source);
|
|
4
16
|
const warnings = [];
|
|
17
|
+
const discovery = discoverJotaiAtomsDetailed(sourceText, fileName);
|
|
18
|
+
warnings.push(...discovery.warnings);
|
|
5
19
|
for (const statement of source.statements) {
|
|
6
20
|
if (!ts.isImportDeclaration(statement) ||
|
|
7
|
-
!
|
|
21
|
+
!isJotaiModuleSpecifier(statement.moduleSpecifier))
|
|
8
22
|
continue;
|
|
9
23
|
const bindings = statement.importClause?.namedBindings;
|
|
10
24
|
if (!bindings || !ts.isNamedImports(bindings))
|
|
@@ -15,159 +29,386 @@ export function discoverJotaiSafetyWarnings(sourceText, fileName = "state.ts") {
|
|
|
15
29
|
continue;
|
|
16
30
|
warnings.push({
|
|
17
31
|
message: "Global taint jotai:getDefaultStore",
|
|
18
|
-
source:
|
|
32
|
+
source: anchor(source, fileName, specifier),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const hydration = discoverHydrationOverrides(source, fileName, imports);
|
|
37
|
+
warnings.push(...hydration.warnings);
|
|
38
|
+
const visit = (node) => {
|
|
39
|
+
if (ts.isJsxSelfClosingElement(node) || ts.isJsxElement(node)) {
|
|
40
|
+
const providerScope = providerScopeFromJsx(node, imports, source);
|
|
41
|
+
if (providerScope === undefined) {
|
|
42
|
+
const tag = ts.isJsxSelfClosingElement(node)
|
|
43
|
+
? node.tagName.getText()
|
|
44
|
+
: node.openingElement.tagName.getText();
|
|
45
|
+
if (tag === imports.providerTag ||
|
|
46
|
+
tag === "Provider" ||
|
|
47
|
+
tag.endsWith(".Provider")) {
|
|
48
|
+
warnings.push({
|
|
49
|
+
message: "Jotai dynamic Provider store unsupported",
|
|
50
|
+
source: anchor(source, fileName, node),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (ts.isCallExpression(node) &&
|
|
56
|
+
ts.isPropertyAccessExpression(node.expression) &&
|
|
57
|
+
node.expression.name.text === "setShouldRemove") {
|
|
58
|
+
warnings.push({
|
|
59
|
+
message: "Jotai atomFamily.setShouldRemove cache lifecycle not modeled",
|
|
60
|
+
source: anchor(source, fileName, node),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (ts.isCallExpression(node) &&
|
|
64
|
+
ts.isPropertyAccessExpression(node.expression) &&
|
|
65
|
+
node.expression.name.text === "unstable_listen") {
|
|
66
|
+
warnings.push({
|
|
67
|
+
message: "Jotai atomFamily.unstable_listen cache lifecycle not modeled",
|
|
68
|
+
source: anchor(source, fileName, node),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
ts.forEachChild(node, visit);
|
|
72
|
+
};
|
|
73
|
+
visit(source);
|
|
74
|
+
for (const decl of discovery.decls) {
|
|
75
|
+
const metadata = metadataFromRecord(decl.metadata);
|
|
76
|
+
if (metadata?.storageKind === "localStorage" && !hasWindowGuard(source)) {
|
|
77
|
+
warnings.push({
|
|
78
|
+
message: `Jotai SSR-unsafe unguarded ${metadata.storageKind} access for ${metadata.atomName}`,
|
|
79
|
+
source: decl.origin === "system" || decl.origin === "library-template"
|
|
80
|
+
? undefined
|
|
81
|
+
: decl.origin,
|
|
19
82
|
});
|
|
20
83
|
}
|
|
21
84
|
}
|
|
22
85
|
return warnings;
|
|
23
86
|
}
|
|
24
87
|
export function discoverJotaiWriteChannels(sourceText, fileName = "state.ts") {
|
|
88
|
+
return discoverJotaiWritesDetailed(sourceText, fileName).channels;
|
|
89
|
+
}
|
|
90
|
+
export function discoverJotaiWritesDetailed(sourceText, fileName = "state.ts") {
|
|
25
91
|
const source = ts.createSourceFile(fileName, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
92
|
+
const imports = resolveJotaiImports(source);
|
|
93
|
+
const discovery = discoverJotaiAtomsDetailed(sourceText, fileName);
|
|
94
|
+
const atomNames = new Set(discovery.atomNames);
|
|
95
|
+
for (const [name] of discovery.atomMetadata)
|
|
96
|
+
atomNames.add(name);
|
|
97
|
+
const derivedWriteEffects = new Map();
|
|
98
|
+
const setterFixedEffects = new Map();
|
|
99
|
+
const atomClassifications = collectAtomClassifications(source, imports);
|
|
100
|
+
for (const [atomName, info] of atomClassifications) {
|
|
101
|
+
if (info.configKind === "writeOnlyDerived" ||
|
|
102
|
+
info.configKind === "readWriteDerived") {
|
|
103
|
+
const writeFn = info.writeFn;
|
|
104
|
+
if (writeFn) {
|
|
105
|
+
const effect = summarizeDerivedWriteBody(writeFn, { atomNames });
|
|
106
|
+
if (effect !== "unsupported")
|
|
107
|
+
derivedWriteEffects.set(atomName, effect);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const resettableVarIds = new Set();
|
|
112
|
+
for (const decl of discovery.decls) {
|
|
113
|
+
const metadata = metadataFromRecord(decl.metadata);
|
|
114
|
+
if (metadata && isResettableKind(metadata.configKind) && decl.var) {
|
|
115
|
+
resettableVarIds.add(decl.var.id);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (imports.hooks.size === 0 &&
|
|
119
|
+
imports.storeCreators.size === 0 &&
|
|
120
|
+
discovery.decls.length === 0) {
|
|
121
|
+
return {
|
|
122
|
+
channels: [],
|
|
123
|
+
warnings: [],
|
|
124
|
+
resetSymbol: imports.resetSymbol,
|
|
125
|
+
resettableVarIds,
|
|
126
|
+
derivedWriteEffects,
|
|
127
|
+
setterFixedEffects,
|
|
128
|
+
storeScopedDecls: [],
|
|
129
|
+
};
|
|
130
|
+
}
|
|
32
131
|
const channels = [];
|
|
132
|
+
const warnings = [];
|
|
133
|
+
const storeNames = new Set();
|
|
33
134
|
const defaultStoreNames = new Set();
|
|
34
|
-
const
|
|
135
|
+
const storeScopedDecls = [];
|
|
136
|
+
const componentStoreScopes = discoverComponentStoreScopes(source, imports);
|
|
137
|
+
const visit = (node, storeScope, componentName) => {
|
|
138
|
+
const nextComponent = componentNameFor(node) ?? componentName;
|
|
139
|
+
const effectiveScope = (nextComponent ? componentStoreScopes.get(nextComponent) : undefined) ??
|
|
140
|
+
storeScope;
|
|
35
141
|
if (ts.isVariableDeclaration(node) &&
|
|
36
142
|
ts.isIdentifier(node.name) &&
|
|
37
|
-
node.initializer
|
|
38
|
-
|
|
39
|
-
|
|
143
|
+
node.initializer) {
|
|
144
|
+
if (isStoreCreatorCall(node.initializer, imports.storeCreators)) {
|
|
145
|
+
storeNames.add(node.name.text);
|
|
146
|
+
if (isGetDefaultStoreCall(node.initializer, imports.storeCreators)) {
|
|
147
|
+
defaultStoreNames.add(node.name.text);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (isHookCall(node.initializer, imports.hooks, "useStore")) {
|
|
151
|
+
storeNames.add(node.name.text);
|
|
152
|
+
}
|
|
40
153
|
}
|
|
41
154
|
if (ts.isVariableDeclaration(node) &&
|
|
42
155
|
ts.isArrayBindingPattern(node.name) &&
|
|
43
156
|
node.initializer &&
|
|
44
|
-
|
|
157
|
+
isHookCall(node.initializer, imports.hooks, "useAtom")) {
|
|
45
158
|
const atomArg = node.initializer.arguments[0];
|
|
159
|
+
const storeScopeForCall = resolveStoreScope(node.initializer, effectiveScope, imports);
|
|
160
|
+
const varId = resolveAtomVarId(atomArg, storeScopeForCall, source, imports, warnings, fileName, defaultStoreNames);
|
|
161
|
+
if (!varId) {
|
|
162
|
+
ts.forEachChild(node, (child) => visit(child, effectiveScope, nextComponent));
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
46
165
|
const reader = node.name.elements[0];
|
|
47
166
|
const setter = node.name.elements.at(-1);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
reader &&
|
|
167
|
+
const src = anchor(source, fileName, node);
|
|
168
|
+
if (reader &&
|
|
51
169
|
ts.isBindingElement(reader) &&
|
|
52
170
|
ts.isIdentifier(reader.name)) {
|
|
53
171
|
channels.push({
|
|
54
|
-
id:
|
|
55
|
-
varId
|
|
172
|
+
id: `${varId}.read`,
|
|
173
|
+
varId,
|
|
56
174
|
symbolName: reader.name.text,
|
|
57
|
-
source:
|
|
58
|
-
file: fileName,
|
|
59
|
-
...lineAndColumn(source, node),
|
|
60
|
-
},
|
|
175
|
+
source: src,
|
|
61
176
|
});
|
|
62
177
|
}
|
|
63
|
-
if (
|
|
64
|
-
ts.isIdentifier(atomArg) &&
|
|
65
|
-
setter &&
|
|
178
|
+
if (setter &&
|
|
66
179
|
ts.isBindingElement(setter) &&
|
|
67
180
|
ts.isIdentifier(setter.name)) {
|
|
68
181
|
channels.push({
|
|
69
|
-
id:
|
|
70
|
-
varId
|
|
182
|
+
id: `${varId}.setter`,
|
|
183
|
+
varId,
|
|
71
184
|
symbolName: setter.name.text,
|
|
72
|
-
source:
|
|
73
|
-
file: fileName,
|
|
74
|
-
...lineAndColumn(source, node),
|
|
75
|
-
},
|
|
185
|
+
source: src,
|
|
76
186
|
});
|
|
77
187
|
}
|
|
78
188
|
}
|
|
79
189
|
if (ts.isVariableDeclaration(node) &&
|
|
80
190
|
ts.isIdentifier(node.name) &&
|
|
81
191
|
node.initializer &&
|
|
82
|
-
|
|
192
|
+
(isHookCall(node.initializer, imports.hooks, "useSetAtom") ||
|
|
193
|
+
isHookCall(node.initializer, imports.hooks, "useResetAtom"))) {
|
|
194
|
+
const hookName = hookImportedName(node.initializer, imports.hooks);
|
|
83
195
|
const atomArg = node.initializer.arguments[0];
|
|
84
|
-
|
|
196
|
+
const storeScopeForCall = resolveStoreScope(node.initializer, effectiveScope, imports);
|
|
197
|
+
const varId = resolveAtomVarId(atomArg, storeScopeForCall, source, imports, warnings, fileName, defaultStoreNames);
|
|
198
|
+
if (!varId) {
|
|
199
|
+
ts.forEachChild(node, (child) => visit(child, effectiveScope, nextComponent));
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const src = anchor(source, fileName, node);
|
|
203
|
+
if (hookName === "useResetAtom") {
|
|
204
|
+
channels.push({
|
|
205
|
+
id: `${varId}.reset`,
|
|
206
|
+
varId,
|
|
207
|
+
symbolName: node.name.text,
|
|
208
|
+
source: src,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
const atomName = atomArg && ts.isIdentifier(atomArg) ? atomArg.text : undefined;
|
|
213
|
+
const derivedEffect = atomName && derivedWriteEffects.has(atomName)
|
|
214
|
+
? derivedWriteEffects.get(atomName)
|
|
215
|
+
: undefined;
|
|
216
|
+
const derivedVarId = derivedEffect
|
|
217
|
+
? (effectTargetVar(derivedEffect) ?? varId)
|
|
218
|
+
: varId;
|
|
219
|
+
if (derivedEffect) {
|
|
220
|
+
setterFixedEffects.set(node.name.text, derivedEffect);
|
|
221
|
+
}
|
|
85
222
|
channels.push({
|
|
86
|
-
id:
|
|
87
|
-
varId:
|
|
223
|
+
id: `${derivedVarId}.setter`,
|
|
224
|
+
varId: derivedVarId,
|
|
88
225
|
symbolName: node.name.text,
|
|
89
|
-
source:
|
|
90
|
-
file: fileName,
|
|
91
|
-
...lineAndColumn(source, node),
|
|
92
|
-
},
|
|
226
|
+
source: src,
|
|
93
227
|
});
|
|
94
228
|
}
|
|
95
229
|
}
|
|
96
230
|
if (ts.isCallExpression(node) &&
|
|
97
231
|
ts.isPropertyAccessExpression(node.expression) &&
|
|
98
|
-
node.expression.name.text === "set"
|
|
232
|
+
(node.expression.name.text === "set" ||
|
|
233
|
+
node.expression.name.text === "get" ||
|
|
234
|
+
node.expression.name.text === "sub") &&
|
|
99
235
|
ts.isIdentifier(node.expression.expression) &&
|
|
100
|
-
|
|
236
|
+
storeNames.has(node.expression.expression.text)) {
|
|
101
237
|
const atomArg = node.arguments[0];
|
|
102
|
-
|
|
238
|
+
const storeScopeForCall = node.expression.expression.text;
|
|
239
|
+
const varId = resolveAtomVarId(atomArg, defaultStoreNames.has(storeScopeForCall)
|
|
240
|
+
? undefined
|
|
241
|
+
: storeScopeForCall, source, imports, warnings, fileName, defaultStoreNames);
|
|
242
|
+
if (varId && node.expression.name.text === "set") {
|
|
103
243
|
channels.push({
|
|
104
|
-
id:
|
|
105
|
-
varId
|
|
106
|
-
symbolName: `${node.expression.expression.text}.set:${atomArg.text}`,
|
|
107
|
-
source:
|
|
108
|
-
file: fileName,
|
|
109
|
-
...lineAndColumn(source, node),
|
|
110
|
-
},
|
|
244
|
+
id: `${varId}.store-set`,
|
|
245
|
+
varId,
|
|
246
|
+
symbolName: `${node.expression.expression.text}.set:${atomArg && ts.isIdentifier(atomArg) ? atomArg.text : "atom"}`,
|
|
247
|
+
source: anchor(source, fileName, node),
|
|
111
248
|
});
|
|
112
249
|
}
|
|
113
250
|
}
|
|
251
|
+
if (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
252
|
+
const providerScope = providerScopeFromJsx(node, imports, source);
|
|
253
|
+
if (providerScope && providerScope !== effectiveScope) {
|
|
254
|
+
storeScopedDecls.push(...duplicateAtomsForStore(discovery.decls, providerScope));
|
|
255
|
+
}
|
|
256
|
+
const childScope = providerScope ?? effectiveScope;
|
|
257
|
+
ts.forEachChild(node, (child) => visit(child, childScope, nextComponent));
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
ts.forEachChild(node, (child) => visit(child, effectiveScope, nextComponent));
|
|
261
|
+
};
|
|
262
|
+
visit(source, undefined, undefined);
|
|
263
|
+
return {
|
|
264
|
+
channels,
|
|
265
|
+
warnings,
|
|
266
|
+
resetSymbol: imports.resetSymbol,
|
|
267
|
+
resettableVarIds,
|
|
268
|
+
derivedWriteEffects,
|
|
269
|
+
setterFixedEffects,
|
|
270
|
+
storeScopedDecls,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
function collectAtomClassifications(source, imports) {
|
|
274
|
+
const typeAliases = typeAliasDeclarations(source);
|
|
275
|
+
const result = new Map();
|
|
276
|
+
const visit = (node) => {
|
|
277
|
+
if (ts.isVariableDeclaration(node) &&
|
|
278
|
+
ts.isIdentifier(node.name) &&
|
|
279
|
+
node.initializer &&
|
|
280
|
+
isAtomCreatorCall(node.initializer, imports.atomCreators) &&
|
|
281
|
+
atomCreatorName(node.initializer, imports.atomCreators) === "atom") {
|
|
282
|
+
const classification = classifyAtomCall(node.initializer, node.name.text, imports, typeAliases);
|
|
283
|
+
const second = node.initializer.arguments[1];
|
|
284
|
+
result.set(node.name.text, {
|
|
285
|
+
configKind: classification.metadata.configKind,
|
|
286
|
+
...(second && isReadFunction(second) ? { writeFn: second } : {}),
|
|
287
|
+
});
|
|
288
|
+
}
|
|
114
289
|
ts.forEachChild(node, visit);
|
|
115
290
|
};
|
|
116
291
|
visit(source);
|
|
117
|
-
return
|
|
292
|
+
return result;
|
|
118
293
|
}
|
|
119
|
-
function
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
294
|
+
function resolveAtomVarId(atomArg, storeScope, source, imports, warnings, fileName, defaultStoreNames = new Set()) {
|
|
295
|
+
const effectiveScope = storeScope && !defaultStoreNames.has(storeScope) ? storeScope : undefined;
|
|
296
|
+
if (!atomArg)
|
|
297
|
+
return undefined;
|
|
298
|
+
if (ts.isIdentifier(atomArg)) {
|
|
299
|
+
return atomVarId(atomArg.text, effectiveScope);
|
|
300
|
+
}
|
|
301
|
+
if (ts.isCallExpression(atomArg) && ts.isIdentifier(atomArg.expression)) {
|
|
302
|
+
const param = atomArg.arguments[0];
|
|
303
|
+
const staticParam = param ? staticFamilyParam(param) : undefined;
|
|
304
|
+
if (!staticParam) {
|
|
305
|
+
warnings.push({
|
|
306
|
+
message: `Jotai dynamic atom family param unsupported for ${atomArg.expression.text}`,
|
|
307
|
+
source: anchor(source, fileName, atomArg),
|
|
308
|
+
});
|
|
309
|
+
return undefined;
|
|
132
310
|
}
|
|
311
|
+
return familyVarId(atomArg.expression.text, staticParam);
|
|
133
312
|
}
|
|
134
|
-
return
|
|
313
|
+
return undefined;
|
|
314
|
+
}
|
|
315
|
+
function resolveStoreScope(call, inheritedScope, imports) {
|
|
316
|
+
const options = call.arguments[1];
|
|
317
|
+
if (options && ts.isObjectLiteralExpression(options)) {
|
|
318
|
+
for (const prop of options.properties) {
|
|
319
|
+
if (!ts.isPropertyAssignment(prop))
|
|
320
|
+
continue;
|
|
321
|
+
const name = propertyName(prop.name);
|
|
322
|
+
if (name === "store" && ts.isIdentifier(prop.initializer)) {
|
|
323
|
+
return prop.initializer.text;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return inheritedScope;
|
|
328
|
+
}
|
|
329
|
+
function isStoreCreatorCall(node, storeCreators) {
|
|
330
|
+
return (ts.isCallExpression(node) &&
|
|
331
|
+
ts.isIdentifier(node.expression) &&
|
|
332
|
+
storeCreators.has(node.expression.text));
|
|
333
|
+
}
|
|
334
|
+
function isGetDefaultStoreCall(node, storeCreators) {
|
|
335
|
+
if (!isStoreCreatorCall(node, storeCreators))
|
|
336
|
+
return false;
|
|
337
|
+
if (!ts.isCallExpression(node) || !ts.isIdentifier(node.expression))
|
|
338
|
+
return false;
|
|
339
|
+
return storeCreators.get(node.expression.text) === "getDefaultStore";
|
|
340
|
+
}
|
|
341
|
+
function effectTargetVar(effect) {
|
|
342
|
+
if (effect.kind === "assign")
|
|
343
|
+
return effect.var;
|
|
344
|
+
if (effect.kind === "seq") {
|
|
345
|
+
for (const child of effect.effects) {
|
|
346
|
+
const target = effectTargetVar(child);
|
|
347
|
+
if (target)
|
|
348
|
+
return target;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return undefined;
|
|
352
|
+
}
|
|
353
|
+
function hasWindowGuard(source) {
|
|
354
|
+
let found = false;
|
|
355
|
+
const visit = (node) => {
|
|
356
|
+
if (ts.isBinaryExpression(node) &&
|
|
357
|
+
node.operatorToken.kind === ts.SyntaxKind.InstanceOfKeyword &&
|
|
358
|
+
ts.isIdentifier(node.right) &&
|
|
359
|
+
node.right.text === "Window") {
|
|
360
|
+
found = true;
|
|
361
|
+
}
|
|
362
|
+
ts.forEachChild(node, visit);
|
|
363
|
+
};
|
|
364
|
+
visit(source);
|
|
365
|
+
return found;
|
|
366
|
+
}
|
|
367
|
+
function anchor(source, fileName, node) {
|
|
368
|
+
const pos = source.getLineAndCharacterOfPosition(node.getStart(source));
|
|
369
|
+
return { file: fileName, line: pos.line + 1, column: pos.character + 1 };
|
|
135
370
|
}
|
|
136
|
-
function setAtomImportNames(source) {
|
|
371
|
+
export function setAtomImportNames(source) {
|
|
372
|
+
const imports = resolveJotaiImports(source);
|
|
137
373
|
const useAtom = new Set();
|
|
138
374
|
const useSetAtom = new Set();
|
|
139
|
-
for (const
|
|
140
|
-
if (
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (!bindings || !ts.isNamedImports(bindings))
|
|
145
|
-
continue;
|
|
146
|
-
for (const specifier of bindings.elements) {
|
|
147
|
-
const imported = specifier.propertyName?.text ?? specifier.name.text;
|
|
148
|
-
if (imported === "useAtom")
|
|
149
|
-
useAtom.add(specifier.name.text);
|
|
150
|
-
if (imported === "useSetAtom")
|
|
151
|
-
useSetAtom.add(specifier.name.text);
|
|
152
|
-
}
|
|
375
|
+
for (const [local, imported] of imports.hooks) {
|
|
376
|
+
if (imported === "useAtom")
|
|
377
|
+
useAtom.add(local);
|
|
378
|
+
if (imported === "useSetAtom")
|
|
379
|
+
useSetAtom.add(local);
|
|
153
380
|
}
|
|
154
381
|
return { useAtom, useSetAtom };
|
|
155
382
|
}
|
|
156
|
-
function
|
|
157
|
-
|
|
383
|
+
export function getDefaultStoreImportNames(source) {
|
|
384
|
+
const imports = resolveJotaiImports(source);
|
|
385
|
+
const names = new Set();
|
|
386
|
+
for (const [local, imported] of imports.storeCreators) {
|
|
387
|
+
if (imported === "getDefaultStore")
|
|
388
|
+
names.add(local);
|
|
389
|
+
}
|
|
390
|
+
return names;
|
|
158
391
|
}
|
|
159
|
-
function isUseAtomLikeCall(node, names) {
|
|
392
|
+
export function isUseAtomLikeCall(node, names) {
|
|
160
393
|
return (ts.isCallExpression(node) &&
|
|
161
394
|
ts.isIdentifier(node.expression) &&
|
|
162
395
|
names.has(node.expression.text));
|
|
163
396
|
}
|
|
164
|
-
function
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
397
|
+
export function jotaiResetSymbols(sourceText, fileName) {
|
|
398
|
+
const source = ts.createSourceFile(fileName, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
|
399
|
+
const imports = resolveJotaiImports(source);
|
|
400
|
+
const symbols = new Set();
|
|
401
|
+
if (imports.resetSymbol)
|
|
402
|
+
symbols.add(imports.resetSymbol);
|
|
403
|
+
symbols.add("RESET");
|
|
404
|
+
return symbols;
|
|
168
405
|
}
|
|
169
|
-
function
|
|
170
|
-
const
|
|
171
|
-
|
|
406
|
+
export function jotaiInitialByVarId(decls) {
|
|
407
|
+
const map = new Map();
|
|
408
|
+
for (const decl of decls) {
|
|
409
|
+
if (decl.var)
|
|
410
|
+
map.set(decl.var.id, decl.var.initial);
|
|
411
|
+
}
|
|
412
|
+
return map;
|
|
172
413
|
}
|
|
173
414
|
//# sourceMappingURL=writes.js.map
|