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.
Files changed (154) hide show
  1. package/dist/cli/cli.js +108 -35
  2. package/dist/cli/cli.js.map +1 -1
  3. package/dist/cli/features/check/command.d.ts +2 -0
  4. package/dist/cli/features/check/command.d.ts.map +1 -1
  5. package/dist/cli/features/check/command.js +11 -3
  6. package/dist/cli/features/check/command.js.map +1 -1
  7. package/dist/cli/features/check/index.d.ts +2 -2
  8. package/dist/cli/features/check/index.d.ts.map +1 -1
  9. package/dist/cli/features/check/index.js +1 -1
  10. package/dist/cli/features/check/index.js.map +1 -1
  11. package/dist/cli/features/check/output.d.ts +22 -7
  12. package/dist/cli/features/check/output.d.ts.map +1 -1
  13. package/dist/cli/features/check/output.js +132 -76
  14. package/dist/cli/features/check/output.js.map +1 -1
  15. package/dist/cli/features/ci/command.d.ts +2 -0
  16. package/dist/cli/features/ci/command.d.ts.map +1 -1
  17. package/dist/cli/features/ci/command.js +21 -0
  18. package/dist/cli/features/ci/command.js.map +1 -1
  19. package/dist/cli/features/ci/index.d.ts +2 -0
  20. package/dist/cli/features/ci/index.d.ts.map +1 -1
  21. package/dist/cli/features/ci/index.js +1 -0
  22. package/dist/cli/features/ci/index.js.map +1 -1
  23. package/dist/cli/features/ci/output.d.ts +19 -0
  24. package/dist/cli/features/ci/output.d.ts.map +1 -0
  25. package/dist/cli/features/ci/output.js +40 -0
  26. package/dist/cli/features/ci/output.js.map +1 -0
  27. package/dist/cli/features/conform/index.d.ts +1 -0
  28. package/dist/cli/features/conform/index.d.ts.map +1 -1
  29. package/dist/cli/features/conform/index.js +1 -0
  30. package/dist/cli/features/conform/index.js.map +1 -1
  31. package/dist/cli/features/conform/output.d.ts +9 -0
  32. package/dist/cli/features/conform/output.d.ts.map +1 -0
  33. package/dist/cli/features/conform/output.js +28 -0
  34. package/dist/cli/features/conform/output.js.map +1 -0
  35. package/dist/cli/features/export/command.d.ts +2 -0
  36. package/dist/cli/features/export/command.d.ts.map +1 -1
  37. package/dist/cli/features/export/command.js +8 -2
  38. package/dist/cli/features/export/command.js.map +1 -1
  39. package/dist/cli/features/export/index.d.ts +1 -0
  40. package/dist/cli/features/export/index.d.ts.map +1 -1
  41. package/dist/cli/features/export/index.js +1 -0
  42. package/dist/cli/features/export/index.js.map +1 -1
  43. package/dist/cli/features/export/output.d.ts +8 -0
  44. package/dist/cli/features/export/output.d.ts.map +1 -0
  45. package/dist/cli/features/export/output.js +14 -0
  46. package/dist/cli/features/export/output.js.map +1 -0
  47. package/dist/cli/features/extract/command.d.ts +9 -0
  48. package/dist/cli/features/extract/command.d.ts.map +1 -1
  49. package/dist/cli/features/extract/command.js +20 -1
  50. package/dist/cli/features/extract/command.js.map +1 -1
  51. package/dist/cli/features/extract/index.d.ts +2 -0
  52. package/dist/cli/features/extract/index.d.ts.map +1 -1
  53. package/dist/cli/features/extract/index.js +1 -0
  54. package/dist/cli/features/extract/index.js.map +1 -1
  55. package/dist/cli/features/extract/output.d.ts +22 -0
  56. package/dist/cli/features/extract/output.d.ts.map +1 -0
  57. package/dist/cli/features/extract/output.js +48 -0
  58. package/dist/cli/features/extract/output.js.map +1 -0
  59. package/dist/cli/features/init/index.d.ts +1 -0
  60. package/dist/cli/features/init/index.d.ts.map +1 -1
  61. package/dist/cli/features/init/index.js +1 -0
  62. package/dist/cli/features/init/index.js.map +1 -1
  63. package/dist/cli/features/init/output.d.ts +4 -0
  64. package/dist/cli/features/init/output.d.ts.map +1 -0
  65. package/dist/cli/features/init/output.js +9 -0
  66. package/dist/cli/features/init/output.js.map +1 -0
  67. package/dist/cli/features/replay/index.d.ts +1 -0
  68. package/dist/cli/features/replay/index.d.ts.map +1 -1
  69. package/dist/cli/features/replay/index.js +1 -0
  70. package/dist/cli/features/replay/index.js.map +1 -1
  71. package/dist/cli/features/replay/output.d.ts +10 -0
  72. package/dist/cli/features/replay/output.d.ts.map +1 -0
  73. package/dist/cli/features/replay/output.js +37 -0
  74. package/dist/cli/features/replay/output.js.map +1 -0
  75. package/dist/cli/output.d.ts +28 -0
  76. package/dist/cli/output.d.ts.map +1 -0
  77. package/dist/cli/output.js +64 -0
  78. package/dist/cli/output.js.map +1 -0
  79. package/dist/extract/engine/ts/context.d.ts.map +1 -1
  80. package/dist/extract/engine/ts/context.js +7 -1
  81. package/dist/extract/engine/ts/context.js.map +1 -1
  82. package/dist/extract/engine/ts/react-source-transitions.d.ts +4 -1
  83. package/dist/extract/engine/ts/react-source-transitions.d.ts.map +1 -1
  84. package/dist/extract/engine/ts/react-source-transitions.js +11 -2
  85. package/dist/extract/engine/ts/react-source-transitions.js.map +1 -1
  86. package/dist/extract/engine/ts/transition/expressions.d.ts +1 -1
  87. package/dist/extract/engine/ts/transition/expressions.d.ts.map +1 -1
  88. package/dist/extract/engine/ts/transition/expressions.js +12 -1
  89. package/dist/extract/engine/ts/transition/expressions.js.map +1 -1
  90. package/dist/extract/engine/ts/transition/handlers.d.ts +3 -3
  91. package/dist/extract/engine/ts/transition/handlers.d.ts.map +1 -1
  92. package/dist/extract/engine/ts/transition/handlers.js +10 -7
  93. package/dist/extract/engine/ts/transition/handlers.js.map +1 -1
  94. package/dist/extract/engine/ts/transition/statement-summary.d.ts +6 -2
  95. package/dist/extract/engine/ts/transition/statement-summary.d.ts.map +1 -1
  96. package/dist/extract/engine/ts/transition/statement-summary.js +40 -6
  97. package/dist/extract/engine/ts/transition/statement-summary.js.map +1 -1
  98. package/dist/extract/engine/ts/types.d.ts +3 -0
  99. package/dist/extract/engine/ts/types.d.ts.map +1 -1
  100. package/dist/extract/sources/jotai/derived-writes.d.ts +11 -0
  101. package/dist/extract/sources/jotai/derived-writes.d.ts.map +1 -0
  102. package/dist/extract/sources/jotai/derived-writes.js +141 -0
  103. package/dist/extract/sources/jotai/derived-writes.js.map +1 -0
  104. package/dist/extract/sources/jotai/discover.d.ts +16 -0
  105. package/dist/extract/sources/jotai/discover.d.ts.map +1 -1
  106. package/dist/extract/sources/jotai/discover.js +163 -46
  107. package/dist/extract/sources/jotai/discover.js.map +1 -1
  108. package/dist/extract/sources/jotai/domains.d.ts +14 -1
  109. package/dist/extract/sources/jotai/domains.d.ts.map +1 -1
  110. package/dist/extract/sources/jotai/domains.js +481 -70
  111. package/dist/extract/sources/jotai/domains.js.map +1 -1
  112. package/dist/extract/sources/jotai/harness.d.ts +4 -1
  113. package/dist/extract/sources/jotai/harness.d.ts.map +1 -1
  114. package/dist/extract/sources/jotai/harness.js +10 -3
  115. package/dist/extract/sources/jotai/harness.js.map +1 -1
  116. package/dist/extract/sources/jotai/hydration.d.ts +16 -0
  117. package/dist/extract/sources/jotai/hydration.d.ts.map +1 -0
  118. package/dist/extract/sources/jotai/hydration.js +116 -0
  119. package/dist/extract/sources/jotai/hydration.js.map +1 -0
  120. package/dist/extract/sources/jotai/ids.d.ts +7 -0
  121. package/dist/extract/sources/jotai/ids.d.ts.map +1 -0
  122. package/dist/extract/sources/jotai/ids.js +23 -0
  123. package/dist/extract/sources/jotai/ids.js.map +1 -0
  124. package/dist/extract/sources/jotai/imports.d.ts +23 -0
  125. package/dist/extract/sources/jotai/imports.d.ts.map +1 -0
  126. package/dist/extract/sources/jotai/imports.js +111 -0
  127. package/dist/extract/sources/jotai/imports.js.map +1 -0
  128. package/dist/extract/sources/jotai/jsx.d.ts +4 -0
  129. package/dist/extract/sources/jotai/jsx.d.ts.map +1 -0
  130. package/dist/extract/sources/jotai/jsx.js +52 -0
  131. package/dist/extract/sources/jotai/jsx.js.map +1 -0
  132. package/dist/extract/sources/jotai/plugin.d.ts.map +1 -1
  133. package/dist/extract/sources/jotai/plugin.js +9 -2
  134. package/dist/extract/sources/jotai/plugin.js.map +1 -1
  135. package/dist/extract/sources/jotai/stores.d.ts +3 -0
  136. package/dist/extract/sources/jotai/stores.d.ts.map +1 -0
  137. package/dist/extract/sources/jotai/stores.js +40 -0
  138. package/dist/extract/sources/jotai/stores.js.map +1 -0
  139. package/dist/extract/sources/jotai/transitions.d.ts.map +1 -1
  140. package/dist/extract/sources/jotai/transitions.js +16 -5
  141. package/dist/extract/sources/jotai/transitions.js.map +1 -1
  142. package/dist/extract/sources/jotai/types.d.ts +22 -0
  143. package/dist/extract/sources/jotai/types.d.ts.map +1 -0
  144. package/dist/extract/sources/jotai/types.js +86 -0
  145. package/dist/extract/sources/jotai/types.js.map +1 -0
  146. package/dist/extract/sources/jotai/writes.d.ts +23 -1
  147. package/dist/extract/sources/jotai/writes.d.ts.map +1 -1
  148. package/dist/extract/sources/jotai/writes.js +330 -89
  149. package/dist/extract/sources/jotai/writes.js.map +1 -1
  150. package/dist/extract/sources/shared/react-transition-extract.d.ts +3 -0
  151. package/dist/extract/sources/shared/react-transition-extract.d.ts.map +1 -1
  152. package/dist/extract/sources/shared/react-transition-extract.js +5 -0
  153. package/dist/extract/sources/shared/react-transition-extract.js.map +1 -1
  154. 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":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,EAClB,QAAQ,SAAa,GACpB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,YAAY,CAAA;CAAE,EAAE,CA2B9C;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,MAAM,EAClB,QAAQ,SAAa,GACpB,YAAY,EAAE,CAmHhB"}
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
- !isJotaiModule(statement.moduleSpecifier))
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: { file: fileName, ...lineAndColumn(source, specifier) },
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 setters = setAtomImportNames(source);
27
- const defaultStoreGetters = getDefaultStoreImportNames(source);
28
- if (setters.useAtom.size === 0 &&
29
- setters.useSetAtom.size === 0 &&
30
- defaultStoreGetters.size === 0)
31
- return [];
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 visit = (node) => {
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
- isGetDefaultStoreCall(node.initializer, defaultStoreGetters)) {
39
- defaultStoreNames.add(node.name.text);
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
- isUseAtomLikeCall(node.initializer, setters.useAtom)) {
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
- if (atomArg &&
49
- ts.isIdentifier(atomArg) &&
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: `atom:${atomArg.text}.read`,
55
- varId: `atom:${atomArg.text}`,
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 (atomArg &&
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: `atom:${atomArg.text}.setter`,
70
- varId: `atom:${atomArg.text}`,
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
- isUseAtomLikeCall(node.initializer, setters.useSetAtom)) {
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
- if (atomArg && ts.isIdentifier(atomArg)) {
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: `atom:${atomArg.text}.setter`,
87
- varId: `atom:${atomArg.text}`,
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
- defaultStoreNames.has(node.expression.expression.text)) {
236
+ storeNames.has(node.expression.expression.text)) {
101
237
  const atomArg = node.arguments[0];
102
- if (atomArg && ts.isIdentifier(atomArg)) {
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: `atom:${atomArg.text}.store-set`,
105
- varId: `atom:${atomArg.text}`,
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 channels;
292
+ return result;
118
293
  }
119
- function getDefaultStoreImportNames(source) {
120
- const names = new Set();
121
- for (const statement of source.statements) {
122
- if (!ts.isImportDeclaration(statement) ||
123
- !isJotaiModule(statement.moduleSpecifier))
124
- continue;
125
- const bindings = statement.importClause?.namedBindings;
126
- if (!bindings || !ts.isNamedImports(bindings))
127
- continue;
128
- for (const specifier of bindings.elements) {
129
- const imported = specifier.propertyName?.text ?? specifier.name.text;
130
- if (imported === "getDefaultStore")
131
- names.add(specifier.name.text);
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 names;
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 statement of source.statements) {
140
- if (!ts.isImportDeclaration(statement) ||
141
- !isJotaiModule(statement.moduleSpecifier))
142
- continue;
143
- const bindings = statement.importClause?.namedBindings;
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 isJotaiModule(moduleSpecifier) {
157
- return (ts.isStringLiteral(moduleSpecifier) && moduleSpecifier.text === "jotai");
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 isGetDefaultStoreCall(node, names) {
165
- return (ts.isCallExpression(node) &&
166
- ts.isIdentifier(node.expression) &&
167
- names.has(node.expression.text));
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 lineAndColumn(source, node) {
170
- const pos = source.getLineAndCharacterOfPosition(node.getStart(source));
171
- return { line: pos.line + 1, column: pos.character + 1 };
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