@astryxdesign/native 0.7.4-canary.720bb10 → 0.7.5-canary.04434e7

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 (119) hide show
  1. package/README.md +116 -4
  2. package/apple/Sources/AstryxNative/Generated/AstryxBase.swift +1 -1
  3. package/apple/Sources/AstryxNative/Generated/AstryxNode.swift +69 -0
  4. package/apple/Sources/AstryxNative/Generated/AstryxWire.swift +67 -0
  5. package/apple/Sources/AstryxNative/Generated/Badge.swift +89 -0
  6. package/apple/Sources/AstryxNative/Generated/Button.swift +154 -0
  7. package/apple/Sources/AstryxNative/Generated/Card.swift +117 -0
  8. package/apple/Sources/AstryxNative/Generated/Divider.swift +97 -0
  9. package/apple/Sources/AstryxNative/Generated/HStack.swift +308 -0
  10. package/apple/Sources/AstryxNative/Generated/Heading.swift +169 -0
  11. package/apple/Sources/AstryxNative/Generated/ProgressBar.swift +144 -0
  12. package/apple/Sources/AstryxNative/Generated/Selector.swift +133 -9
  13. package/apple/Sources/AstryxNative/Generated/Switch.swift +202 -0
  14. package/apple/Sources/AstryxNative/Generated/Text.swift +172 -0
  15. package/apple/Sources/AstryxNative/Generated/TextInput.swift +243 -0
  16. package/apple/Sources/AstryxNative/Generated/VStack.swift +308 -0
  17. package/apple/Sources/AstryxNative/Logic/AstryxLogicHost.swift +102 -0
  18. package/apple/Tests/AstryxNativeTests/ControlPropsTests.swift +29 -0
  19. package/apple/Tests/AstryxNativeTests/LogicHostTests.swift +85 -0
  20. package/apple/Tests/AstryxNativeTests/WireTests.swift +53 -0
  21. package/dist/components/Badge.d.ts +10 -0
  22. package/dist/components/Badge.d.ts.map +1 -0
  23. package/dist/components/Badge.js +7 -0
  24. package/dist/components/Button.d.ts +10 -0
  25. package/dist/components/Button.d.ts.map +1 -0
  26. package/dist/components/Button.js +15 -0
  27. package/dist/components/Card.d.ts +10 -0
  28. package/dist/components/Card.d.ts.map +1 -0
  29. package/dist/components/Card.js +7 -0
  30. package/dist/components/Divider.d.ts +10 -0
  31. package/dist/components/Divider.d.ts.map +1 -0
  32. package/dist/components/Divider.js +6 -0
  33. package/dist/components/HStack.d.ts +10 -0
  34. package/dist/components/HStack.d.ts.map +1 -0
  35. package/dist/components/HStack.js +9 -0
  36. package/dist/components/Heading.d.ts +10 -0
  37. package/dist/components/Heading.d.ts.map +1 -0
  38. package/dist/components/Heading.js +14 -0
  39. package/dist/components/ProgressBar.d.ts +10 -0
  40. package/dist/components/ProgressBar.d.ts.map +1 -0
  41. package/dist/components/ProgressBar.js +5 -0
  42. package/dist/components/Switch.d.ts +10 -0
  43. package/dist/components/Switch.d.ts.map +1 -0
  44. package/dist/components/Switch.js +6 -0
  45. package/dist/components/Text.d.ts +10 -0
  46. package/dist/components/Text.d.ts.map +1 -0
  47. package/dist/components/Text.js +13 -0
  48. package/dist/components/TextInput.d.ts +10 -0
  49. package/dist/components/TextInput.d.ts.map +1 -0
  50. package/dist/components/TextInput.js +9 -0
  51. package/dist/components/VStack.d.ts +10 -0
  52. package/dist/components/VStack.d.ts.map +1 -0
  53. package/dist/components/VStack.js +9 -0
  54. package/dist/components/index.d.ts.map +1 -1
  55. package/dist/components/index.js +25 -1
  56. package/dist/components/stackShared.d.ts +9 -0
  57. package/dist/components/stackShared.d.ts.map +1 -0
  58. package/dist/components/stackShared.js +4 -0
  59. package/dist/contract/fromComponentDoc.d.ts +44 -5
  60. package/dist/contract/fromComponentDoc.d.ts.map +1 -1
  61. package/dist/contract/fromComponentDoc.js +47 -4
  62. package/dist/contract/generateSwift.d.ts.map +1 -1
  63. package/dist/contract/generateSwift.js +193 -10
  64. package/dist/contract/generateTypeScript.d.ts.map +1 -1
  65. package/dist/contract/generateTypeScript.js +69 -9
  66. package/dist/contract/index.d.ts +7 -3
  67. package/dist/contract/index.d.ts.map +1 -1
  68. package/dist/contract/index.js +2 -1
  69. package/dist/contract/parseDocType.d.ts +5 -2
  70. package/dist/contract/parseDocType.d.ts.map +1 -1
  71. package/dist/contract/parseDocType.js +34 -5
  72. package/dist/contract/rules.d.ts +5 -2
  73. package/dist/contract/rules.d.ts.map +1 -1
  74. package/dist/contract/rules.js +8 -4
  75. package/dist/contract/types.d.ts +11 -0
  76. package/dist/contract/types.d.ts.map +1 -1
  77. package/dist/logic/connectBridge.d.ts +29 -0
  78. package/dist/logic/connectBridge.d.ts.map +1 -0
  79. package/dist/logic/connectBridge.js +32 -0
  80. package/dist/logic/createLogicCore.d.ts +44 -0
  81. package/dist/logic/createLogicCore.d.ts.map +1 -0
  82. package/dist/logic/createLogicCore.js +40 -0
  83. package/dist/logic/index.d.ts +12 -0
  84. package/dist/logic/index.d.ts.map +1 -0
  85. package/dist/logic/index.js +10 -0
  86. package/dist/types/android.d.ts +136 -2
  87. package/dist/types/core.d.ts +150 -0
  88. package/dist/types/ios.d.ts +136 -2
  89. package/dist/types/macos.d.ts +136 -2
  90. package/dist/types/shared.d.ts +136 -2
  91. package/dist/types/windows.d.ts +136 -2
  92. package/package.json +10 -4
  93. package/src/components/Badge.ts +18 -0
  94. package/src/components/Button.ts +26 -0
  95. package/src/components/Card.ts +18 -0
  96. package/src/components/Divider.ts +17 -0
  97. package/src/components/HStack.ts +20 -0
  98. package/src/components/Heading.ts +25 -0
  99. package/src/components/ProgressBar.ts +16 -0
  100. package/src/components/Switch.ts +17 -0
  101. package/src/components/Text.ts +24 -0
  102. package/src/components/TextInput.ts +20 -0
  103. package/src/components/VStack.ts +20 -0
  104. package/src/components/index.ts +25 -1
  105. package/src/components/stackShared.ts +14 -0
  106. package/src/contract/contracts.test.ts +58 -0
  107. package/src/contract/fromComponentDoc.test.ts +97 -0
  108. package/src/contract/fromComponentDoc.ts +106 -9
  109. package/src/contract/generateSwift.ts +223 -10
  110. package/src/contract/generateTypeScript.ts +83 -10
  111. package/src/contract/index.ts +13 -4
  112. package/src/contract/parseDocType.test.ts +45 -0
  113. package/src/contract/parseDocType.ts +41 -6
  114. package/src/contract/rules.ts +11 -4
  115. package/src/contract/types.ts +6 -0
  116. package/src/logic/connectBridge.ts +72 -0
  117. package/src/logic/createLogicCore.ts +97 -0
  118. package/src/logic/index.ts +19 -0
  119. package/src/logic/logic.test.ts +160 -0
@@ -2,9 +2,13 @@
2
2
  /**
3
3
  * @file contract/generateSwift.ts
4
4
  * @input Component contracts
5
- * @output Swift sources for the Apple platforms: shared base props and one file
6
- * per component, with the iOS and macOS contracts behind `#if os(...)`
7
- * @position Produces the Swift binding (AST-082 FR5). Generated files are
5
+ * @output Swift sources for the Apple platforms: shared base props, the wire
6
+ * (AstryxNode, AstryxAction), and one file per component with the iOS and
7
+ * macOS contracts behind `#if os(...)`
8
+ * @position Produces the Swift binding (AST-082 FR5). Each component gets
9
+ * `<Name>Props`, the contract a SwiftUI view takes, and `<Name>Node`, the
10
+ * same contract as JSON a TypeScript core sends (arm C), which turns into
11
+ * props whose callbacks send `AstryxAction`s back. Generated files are
8
12
  * committed under apple/ so a Swift package can pin a commit
9
13
  */
10
14
  import { SWIFT_KEYWORDS } from './names.js';
@@ -13,9 +17,14 @@ const APPLE_PLATFORMS = [
13
17
  { platform: 'ios', condition: 'os(iOS)' },
14
18
  { platform: 'macos', condition: 'os(macOS)' },
15
19
  ];
20
+ const RECORD_CONFORMANCES = 'Equatable, Codable, Sendable';
16
21
  const camel = (text) => text.replace(/[-_ ]+([a-zA-Z0-9])/g, (_, ch) => ch.toUpperCase());
17
22
  const pascal = (text) => camel(text).replace(/^./, ch => ch.toUpperCase());
18
23
  const ident = (name) => SWIFT_KEYWORDS.has(name) ? `\`${name}\`` : name;
24
+ /** `1` → `v1`, `0.5` → `v0_5`, `-1` → `vMinus1`. */
25
+ function numberCaseName(value) {
26
+ return `v${String(value).replace('-', 'Minus').replace('.', '_')}`;
27
+ }
19
28
  function caseName(value) {
20
29
  const name = camel(value.replace(/[^A-Za-z0-9_-]/g, '-'));
21
30
  return ident(/^[0-9]/.test(name) ? `v${name}` : name || 'empty');
@@ -34,18 +43,27 @@ class SwiftWriter {
34
43
  case 'enum': {
35
44
  const name = `${owner}${pascal(prop)}`;
36
45
  const cases = type.values.map(value => ` case ${caseName(value)} = "${value}"`);
37
- this.decls.push(`public enum ${name}: String, CaseIterable, Sendable {\n${cases.join('\n')}\n}`);
46
+ this.decls.push(`public enum ${name}: String, CaseIterable, Codable, Sendable {\n${cases.join('\n')}\n}`);
47
+ return name;
48
+ }
49
+ case 'numberEnum': {
50
+ const name = `${owner}${pascal(prop)}`;
51
+ const raw = type.values.every(Number.isInteger) ? 'Int' : 'Double';
52
+ const cases = type.values.map(value => ` case ${numberCaseName(value)} = ${value}`);
53
+ this.decls.push(`public enum ${name}: ${raw}, CaseIterable, Codable, Sendable {\n${cases.join('\n')}\n}`);
38
54
  return name;
39
55
  }
40
56
  case 'array':
41
57
  return `[${this.type(owner, prop, type.of)}]`;
42
58
  case 'record': {
43
59
  const name = `${owner}${pascal(prop)}`;
44
- this.decls.push(this.struct(name, type.fields, 'Equatable, Sendable'));
60
+ this.decls.push(this.struct(name, type.fields, RECORD_CONFORMANCES));
45
61
  return name;
46
62
  }
47
63
  case 'fn':
48
64
  return `(${type.args.map((arg, i) => this.type(owner, `${prop}Arg${i}`, arg)).join(', ')}) -> Void`;
65
+ case 'content':
66
+ return '[AstryxNode]';
49
67
  case 'named':
50
68
  return type.name;
51
69
  }
@@ -79,15 +97,65 @@ class SwiftWriter {
79
97
  ].join('\n');
80
98
  }
81
99
  }
100
+ /** Props without content slots: a SwiftUI view takes content as a builder. */
101
+ function withoutContent(props) {
102
+ return Object.fromEntries(Object.entries(props).filter(([, spec]) => spec.type.kind !== 'content'));
103
+ }
104
+ function withoutCallbacks(props) {
105
+ return Object.fromEntries(Object.entries(props).filter(([, spec]) => spec.type.kind !== 'fn'));
106
+ }
107
+ /** `<Name>Node`: the component as JSON from a TypeScript core (arm C). */
108
+ function nodeStruct(writer, contract, props) {
109
+ const name = contract.name;
110
+ const data = writer.fields(name, withoutCallbacks(props));
111
+ const callbacks = Object.entries(props).filter(([, spec]) => spec.type.kind === 'fn');
112
+ // Each callback the core listens to (`events`) sends an action with the
113
+ // callback's arguments; one it does not listen to stays nil.
114
+ const binding = Object.entries(withoutContent(props)).map(([prop, spec]) => {
115
+ if (spec.type.kind !== 'fn') {
116
+ return ` ${prop}: props.${ident(prop)}`;
117
+ }
118
+ const params = spec.type.args.map((_, i) => `arg${i}`);
119
+ const values = params.map(param => `AstryxValue(${param})`).join(', ');
120
+ const closure = `{ ${params.length > 0 ? `${params.join(', ')} in ` : ''}send(AstryxAction(key: key, component: "${name}", event: "${prop}", args: [${values}])) }`;
121
+ return spec.optional
122
+ ? ` ${prop}: listens("${prop}") ? ${closure} : nil`
123
+ : ` ${prop}: ${closure}`;
124
+ });
125
+ return [
126
+ `public struct ${name}Node: Decodable, Equatable, Sendable {`,
127
+ ` public struct Props: Decodable, Equatable, Sendable {`,
128
+ ...data.map(field => ` ${field.decl}`),
129
+ ' }',
130
+ ' public let key: String',
131
+ ' public let base: AstryxBaseProps?',
132
+ ' public let props: Props',
133
+ ` /// The callbacks the core listens to, by prop name.`,
134
+ ' public let events: [String]?',
135
+ '',
136
+ ` public func listens(_ event: String) -> Bool { events?.contains(event) ?? false }`,
137
+ '',
138
+ ` /// The contract a ${name} view takes; its callbacks send actions to the core.`,
139
+ ` public func viewProps(send: @escaping @Sendable (AstryxAction) -> Void) -> ${name}Props {`,
140
+ ...(callbacks.length > 0 ? [' let key = self.key'] : []),
141
+ ` return ${name}Props(`,
142
+ [...binding, ' base: base ?? AstryxBaseProps()'].join(',\n'),
143
+ ' )',
144
+ ' }',
145
+ '}',
146
+ ].join('\n');
147
+ }
82
148
  function componentFile(contract) {
83
149
  const shared = new SwiftWriter();
84
- const typeDecls = Object.entries(contract.types).map(([name, fields]) => shared.struct(name, fields, 'Equatable, Sendable'));
150
+ const typeDecls = Object.entries(contract.types).map(([name, fields]) => shared.struct(name, fields, RECORD_CONFORMANCES));
85
151
  // Core enums and records are declared once, outside the platform blocks.
86
152
  shared.fields(`${contract.name}`, contract.core);
87
153
  const variants = APPLE_PLATFORMS.map(({ platform, condition }) => {
88
154
  const writer = new SwiftWriter();
89
155
  const extra = contract.platforms[platform] ?? {};
90
- const fields = writer.fields(contract.name, { ...contract.core, ...extra });
156
+ const all = { ...contract.core, ...extra };
157
+ const fields = writer.fields(contract.name, withoutContent(all));
158
+ const node = nodeStruct(writer, contract, all);
91
159
  // Core-prop declarations already live outside the platform blocks; keep
92
160
  // only the declarations this platform's own props need.
93
161
  writer.decls.length = 0;
@@ -104,16 +172,127 @@ function componentFile(contract) {
104
172
  ' }',
105
173
  '}',
106
174
  ].join('\n');
107
- return `#if ${condition}\n${[...writer.decls, struct].join('\n')}\n#endif`;
175
+ return `#if ${condition}\n${[...writer.decls, struct, node].join('\n')}\n#endif`;
108
176
  });
109
177
  return (HEADER + [...typeDecls, ...shared.decls, ...variants].join('\n') + '\n');
110
178
  }
179
+ /** `AstryxNode`: one case per component, decoded by its `component` name. */
180
+ function nodeFile(contracts) {
181
+ const caseOf = (name) => camel(name.replace(/^./, ch => ch.toLowerCase()));
182
+ return (HEADER +
183
+ [
184
+ 'import Foundation',
185
+ '',
186
+ '#if os(iOS) || os(macOS)',
187
+ '/// One Astryx component in a tree a TypeScript core sends, by its `component` name.',
188
+ '/// A node this binding cannot read decodes as `unsupported`: an unknown component,',
189
+ '/// or a known one with a value its enums lack or a required prop missing. An older',
190
+ "/// app then keeps drawing the rest of a newer core's tree.",
191
+ 'public enum AstryxNode: Decodable, Equatable, Sendable {',
192
+ ...contracts.map(c => ` case ${ident(caseOf(c.name))}(${c.name}Node)`),
193
+ ' case unsupported(component: String, key: String)',
194
+ '',
195
+ ' public var key: String {',
196
+ ' switch self {',
197
+ ...contracts.map(c => ` case .${ident(caseOf(c.name))}(let node): return node.key`),
198
+ ' case .unsupported(_, let key): return key',
199
+ ' }',
200
+ ' }',
201
+ '',
202
+ ' private enum Keys: String, CodingKey { case component, key }',
203
+ '',
204
+ ' public init(from decoder: any Decoder) throws {',
205
+ ' let container = try decoder.container(keyedBy: Keys.self)',
206
+ ' let component = try container.decode(String.self, forKey: .component)',
207
+ ' let key = try container.decode(String.self, forKey: .key)',
208
+ ' do {',
209
+ ' switch component {',
210
+ ...contracts.map(c => ` case "${c.name}": self = .${ident(caseOf(c.name))}(try ${c.name}Node(from: decoder))`),
211
+ ' default: self = .unsupported(component: component, key: key)',
212
+ ' }',
213
+ ' } catch {',
214
+ ' self = .unsupported(component: component, key: key)',
215
+ ' }',
216
+ ' }',
217
+ '}',
218
+ '#endif',
219
+ ].join('\n') +
220
+ '\n');
221
+ }
222
+ const WIRE_FILE = HEADER +
223
+ `import Foundation
224
+
225
+ /// A JSON value: a portable callback argument on its way to the core.
226
+ public enum AstryxValue: Codable, Equatable, Sendable {
227
+ case null
228
+ case bool(Bool)
229
+ case number(Double)
230
+ case string(String)
231
+ case array([AstryxValue])
232
+ case object([String: AstryxValue])
233
+
234
+ /// Any portable value (a contract's strings, numbers, enums, and records) as JSON.
235
+ public init<T: Encodable>(_ value: T) {
236
+ guard let data = try? JSONEncoder().encode(value),
237
+ let decoded = try? JSONDecoder().decode(AstryxValue.self, from: data) else {
238
+ self = .null
239
+ return
240
+ }
241
+ self = decoded
242
+ }
243
+
244
+ public init(from decoder: any Decoder) throws {
245
+ let container = try decoder.singleValueContainer()
246
+ if container.decodeNil() { self = .null }
247
+ else if let value = try? container.decode(Bool.self) { self = .bool(value) }
248
+ else if let value = try? container.decode(Double.self) { self = .number(value) }
249
+ else if let value = try? container.decode(String.self) { self = .string(value) }
250
+ else if let value = try? container.decode([AstryxValue].self) { self = .array(value) }
251
+ else { self = .object(try container.decode([String: AstryxValue].self)) }
252
+ }
253
+
254
+ public func encode(to encoder: any Encoder) throws {
255
+ var container = encoder.singleValueContainer()
256
+ switch self {
257
+ case .null: try container.encodeNil()
258
+ case .bool(let value): try container.encode(value)
259
+ case .number(let value): try container.encode(value)
260
+ case .string(let value): try container.encode(value)
261
+ case .array(let value): try container.encode(value)
262
+ case .object(let value): try container.encode(value)
263
+ }
264
+ }
265
+ }
266
+
267
+ /// A callback a view called: which node, which prop, and its arguments.
268
+ public struct AstryxAction: Codable, Equatable, Sendable {
269
+ public let key: String
270
+ public let component: String
271
+ public let event: String
272
+ public let args: [AstryxValue]
273
+
274
+ public init(key: String, component: String, event: String, args: [AstryxValue]) {
275
+ self.key = key
276
+ self.component = component
277
+ self.event = event
278
+ self.args = args
279
+ }
280
+
281
+ /// The JSON the core receives.
282
+ public var json: String {
283
+ let encoder = JSONEncoder()
284
+ encoder.outputFormatting = [.sortedKeys, .withoutEscapingSlashes]
285
+ guard let data = try? encoder.encode(self) else { return "{}" }
286
+ return String(decoding: data, as: UTF8.self)
287
+ }
288
+ }
289
+ `;
111
290
  const BASE_FILE = HEADER +
112
291
  [
113
292
  'public enum AstryxBaseTarget: String, Sendable { case root, trigger, control, container }',
114
293
  '',
115
294
  '/// Base props shared by every platform (AST-082 FR7).',
116
- 'public struct AstryxBaseProps: Equatable, Sendable {',
295
+ 'public struct AstryxBaseProps: Equatable, Codable, Sendable {',
117
296
  ' public var id: String?',
118
297
  ' public var isHidden: Bool?',
119
298
  ' public init(id: String? = nil, isHidden: Bool? = nil) {',
@@ -125,7 +304,11 @@ const BASE_FILE = HEADER +
125
304
  '\n';
126
305
  /** Returns file name to contents, relative to the generated Swift folder. */
127
306
  export function generateSwift(contracts) {
128
- const files = { 'AstryxBase.swift': BASE_FILE };
307
+ const files = {
308
+ 'AstryxBase.swift': BASE_FILE,
309
+ 'AstryxNode.swift': nodeFile(contracts),
310
+ 'AstryxWire.swift': WIRE_FILE,
311
+ };
129
312
  for (const contract of contracts) {
130
313
  files[`${contract.name}.swift`] = componentFile(contract);
131
314
  }
@@ -1 +1 @@
1
- {"version":3,"file":"generateTypeScript.d.ts","sourceRoot":"","sources":["../../src/contract/generateTypeScript.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAC,iBAAiB,EAAoB,MAAM,YAAY,CAAC;AA2FrE,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,SAAS,iBAAiB,EAAE,GACtC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASxB"}
1
+ {"version":3,"file":"generateTypeScript.d.ts","sourceRoot":"","sources":["../../src/contract/generateTypeScript.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAC,iBAAiB,EAA8B,MAAM,YAAY,CAAC;AAoK/E,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,SAAS,iBAAiB,EAAE,GACtC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASxB"}
@@ -8,7 +8,11 @@
8
8
  */
9
9
  import { NATIVE_PLATFORMS } from '../platforms.js';
10
10
  const HEADER = '// Generated by @astryxdesign/native. Do not edit.\n';
11
- function tsType(type) {
11
+ /**
12
+ * `content` names the type of one child component: the open
13
+ * `AstryxContentNode` in core contracts, a platform's `AstryxNode` in its wire.
14
+ */
15
+ function tsType(type, content = 'AstryxContentNode') {
12
16
  switch (type.kind) {
13
17
  case 'string':
14
18
  case 'number':
@@ -16,14 +20,18 @@ function tsType(type) {
16
20
  return type.kind;
17
21
  case 'enum':
18
22
  return type.values.map(value => `'${value}'`).join(' | ');
23
+ case 'numberEnum':
24
+ return type.values.join(' | ');
19
25
  case 'array': {
20
- const inner = tsType(type.of);
26
+ const inner = tsType(type.of, content);
21
27
  return `ReadonlyArray<${inner}>`;
22
28
  }
23
29
  case 'record':
24
- return `{${members(type.fields, ' ')}}`;
30
+ return `{${members(type.fields, ' ', content)}}`;
25
31
  case 'fn':
26
- return `(${type.args.map((arg, i) => `arg${i}: ${tsType(arg)}`).join(', ')}) => void`;
32
+ return `(${type.args.map((arg, i) => `arg${i}: ${tsType(arg, content)}`).join(', ')}) => void`;
33
+ case 'content':
34
+ return `ReadonlyArray<${content}>`;
27
35
  case 'named':
28
36
  return type.name;
29
37
  }
@@ -31,9 +39,9 @@ function tsType(type) {
31
39
  function key(name) {
32
40
  return /^[A-Za-z_$][\w$]*$/.test(name) ? name : `'${name}'`;
33
41
  }
34
- function members(props, separator = '\n ') {
42
+ function members(props, separator = '\n ', content = 'AstryxContentNode') {
35
43
  return Object.entries(props)
36
- .map(([name, spec]) => `${key(name)}${spec.optional ? '?' : ''}: ${tsType(spec.type)};`)
44
+ .map(([name, spec]) => `${key(name)}${spec.optional ? '?' : ''}: ${tsType(spec.type, content)};`)
37
45
  .join(separator);
38
46
  }
39
47
  function coreFile(contracts) {
@@ -49,19 +57,65 @@ function coreFile(contracts) {
49
57
  return (HEADER +
50
58
  '/** Base props shared by every platform (AST-082 FR7). */\n' +
51
59
  'export interface AstryxSharedBaseProps {\n id?: string;\n isHidden?: boolean;\n}\n' +
60
+ '/** One child Astryx component in a content slot (AST-082 FR4). */\n' +
61
+ 'export interface AstryxContentNode {\n readonly component: string;\n readonly key: string;\n}\n' +
52
62
  [...typeDecls, ...props].join('\n') +
53
63
  '\n');
54
64
  }
55
65
  function reExports(contracts) {
56
- const names = new Set(['AstryxSharedBaseProps']);
66
+ const names = new Set(['AstryxSharedBaseProps', 'AstryxContentNode']);
57
67
  for (const contract of contracts) {
58
68
  Object.keys(contract.types).forEach(name => names.add(name));
59
69
  names.add(`${contract.name}CoreProps`);
60
70
  }
61
71
  return `export type {${[...names].join(', ')}} from './core.js';\n`;
62
72
  }
73
+ /**
74
+ * The wire a TypeScript core sends a native host (arm C): each component as
75
+ * JSON with its data props, the callbacks it listens to, and the actions a
76
+ * host sends back when a view calls one.
77
+ */
78
+ function wire(contracts, platform) {
79
+ const nodes = [];
80
+ const actions = [];
81
+ for (const contract of contracts) {
82
+ const props = {
83
+ ...contract.core,
84
+ ...(platform ? (contract.platforms[platform] ?? {}) : {}),
85
+ };
86
+ const data = {};
87
+ const events = [];
88
+ for (const [name, spec] of Object.entries(props)) {
89
+ if (spec.type.kind === 'fn') {
90
+ events.push(name);
91
+ actions.push(` | {key: string; component: '${contract.name}'; event: '${name}'; args: [${spec.type.args.map(arg => tsType(arg, 'AstryxNode')).join(', ')}]}`);
92
+ }
93
+ else {
94
+ data[name] = spec;
95
+ }
96
+ }
97
+ nodes.push(`/** ${contract.name} as JSON from a TypeScript core. */\n` +
98
+ `export interface ${contract.name}Node {\n` +
99
+ ` component: '${contract.name}';\n` +
100
+ ' key: string;\n' +
101
+ ' base?: AstryxSharedBaseProps;\n' +
102
+ ` props: {${members(data, ' ', 'AstryxNode')}};\n` +
103
+ (events.length > 0
104
+ ? ` /** The callbacks the core listens to. */\n events?: ReadonlyArray<${events.map(e => `'${e}'`).join(' | ')}>;\n`
105
+ : '') +
106
+ '}');
107
+ }
108
+ return [
109
+ ...nodes,
110
+ '/** Any Astryx component a TypeScript core can send. */',
111
+ `export type AstryxNode = ${contracts.map(c => `${c.name}Node`).join(' | ')};`,
112
+ '/** A callback a native view called, sent back to the core. */',
113
+ `export type AstryxAction =\n${actions.join('\n') || ' never'};`,
114
+ ].join('\n');
115
+ }
63
116
  function platformFile(contracts, platform) {
64
- const imports = `import type {${contracts.map(c => `${c.name}CoreProps`).join(', ')}} from './core.js';\n`;
117
+ const named = contracts.flatMap(c => Object.keys(c.types));
118
+ const imports = `import type {${['AstryxSharedBaseProps', ...new Set(named), ...contracts.map(c => `${c.name}CoreProps`)].join(', ')}} from './core.js';\n`;
65
119
  const components = contracts.map(contract => {
66
120
  const extra = platform ? (contract.platforms[platform] ?? {}) : {};
67
121
  const body = Object.keys(extra).length > 0 ? `\n ${members(extra)}\n` : '';
@@ -72,7 +126,13 @@ function platformFile(contracts, platform) {
72
126
  `export interface ${contract.name}Props extends ${contract.name}CoreProps {${body}}\n` +
73
127
  `export declare function ${contract.name}(props: ${contract.name}Props): unknown;`);
74
128
  });
75
- return HEADER + imports + reExports(contracts) + components.join('\n') + '\n';
129
+ return (HEADER +
130
+ imports +
131
+ reExports(contracts) +
132
+ components.join('\n') +
133
+ '\n' +
134
+ wire(contracts, platform) +
135
+ '\n');
76
136
  }
77
137
  /** Returns file name to contents, relative to the types output folder. */
78
138
  export function generateTypeScript(contracts) {
@@ -2,15 +2,19 @@ import { type ComponentDocLike } from './fromComponentDoc.js';
2
2
  import { type ContractIssue } from './rules.js';
3
3
  import type { ComponentContract } from './types.js';
4
4
  export { fromComponentDoc } from './fromComponentDoc.js';
5
- export type { ComponentDocLike, NativeAdditions } from './fromComponentDoc.js';
5
+ export type { ComponentDocLike, NativeAdditions, SlotKind, } from './fromComponentDoc.js';
6
6
  export { generateSwift } from './generateSwift.js';
7
7
  export { generateTypeScript } from './generateTypeScript.js';
8
8
  export { parseDocType } from './parseDocType.js';
9
9
  export { checkContract, coreNameProblem } from './rules.js';
10
10
  export type { ContractIssue } from './rules.js';
11
11
  export type * from './types.js';
12
- /** Loads one core component's documentation by component name. */
13
- export type ComponentDocLoader = (name: string) => Promise<ComponentDocLike>;
12
+ /**
13
+ * Loads one core documentation file: a component name for
14
+ * `<Name>/<Name>.doc.mjs`, or a path such as `Text/Heading` relative to core's
15
+ * `src` without `.doc.mjs`.
16
+ */
17
+ export type ComponentDocLoader = (file: string) => Promise<ComponentDocLike>;
14
18
  export interface BuiltContracts {
15
19
  readonly contracts: readonly ComponentContract[];
16
20
  readonly warnings: readonly ContractIssue[];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contract/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAAmB,KAAK,gBAAgB,EAAC,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAgB,KAAK,aAAa,EAAC,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,YAAY,CAAC;AAElD,OAAO,EAAC,gBAAgB,EAAC,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAC,gBAAgB,EAAE,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAC,kBAAkB,EAAC,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAC,aAAa,EAAE,eAAe,EAAC,MAAM,YAAY,CAAC;AAC1D,YAAY,EAAC,aAAa,EAAC,MAAM,YAAY,CAAC;AAC9C,mBAAmB,YAAY,CAAC;AAEhC,kEAAkE;AAClE,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAE7E,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACjD,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;CAC7C;AAED,8EAA8E;AAC9E,wBAAsB,cAAc,CAClC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,cAAc,CAAC,CAiBzB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contract/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAAmB,KAAK,gBAAgB,EAAC,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAgB,KAAK,aAAa,EAAC,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,YAAY,CAAC;AAElD,OAAO,EAAC,gBAAgB,EAAC,MAAM,uBAAuB,CAAC;AACvD,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,QAAQ,GACT,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAC,kBAAkB,EAAC,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAC,aAAa,EAAE,eAAe,EAAC,MAAM,YAAY,CAAC;AAC1D,YAAY,EAAC,aAAa,EAAC,MAAM,YAAY,CAAC;AAC9C,mBAAmB,YAAY,CAAC;AAEhC;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAE7E,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACjD,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;CAC7C;AAED,8EAA8E;AAC9E,wBAAsB,cAAc,CAClC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,cAAc,CAAC,CAkBzB"}
@@ -20,7 +20,8 @@ export async function buildContracts(loadDoc) {
20
20
  const warnings = [];
21
21
  const errors = [];
22
22
  for (const additions of NATIVE_COMPONENTS) {
23
- const contract = fromComponentDoc(await loadDoc(additions.name), additions);
23
+ const doc = await loadDoc(additions.doc?.file ?? additions.name);
24
+ const contract = fromComponentDoc(doc, additions);
24
25
  for (const issue of checkContract(contract)) {
25
26
  (issue.level === 'error' ? errors : warnings).push(issue);
26
27
  }
@@ -11,11 +11,14 @@ export type ParsedType = {
11
11
  } | {
12
12
  readonly ok: false;
13
13
  readonly reason: string;
14
+ /** True for a callback whose only arguments are DOM events. */
15
+ readonly eventOnly?: boolean;
14
16
  };
15
17
  /**
16
18
  * Parses a documented type string. Supported portable forms: `string`,
17
- * `number`, `boolean`, closed string unions, arrays, plain object literals,
18
- * callbacks with portable arguments, and named types. A union of different
19
+ * `number`, `boolean`, closed string or number unions, arrays, plain object
20
+ * literals, callbacks with portable arguments (a trailing DOM event argument
21
+ * is the web's part), and named types. A union of different
19
22
  * kinds has no Swift or Kotlin form.
20
23
  */
21
24
  export declare function parseDocType(raw: string): ParsedType;
@@ -1 +1 @@
1
- {"version":3,"file":"parseDocType.d.ts","sourceRoot":"","sources":["../../src/contract/parseDocType.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,EAAW,QAAQ,EAAC,MAAM,YAAY,CAAC;AAEnD,MAAM,MAAM,UAAU,GAClB;IAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAC,GAC5C;IAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAAC;AAuIlD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAwDpD"}
1
+ {"version":3,"file":"parseDocType.d.ts","sourceRoot":"","sources":["../../src/contract/parseDocType.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,EAAW,QAAQ,EAAC,MAAM,YAAY,CAAC;AAEnD,MAAM,MAAM,UAAU,GAClB;IAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAC,GAC5C;IACE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+DAA+D;IAC/D,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AA8JN;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CA8DpD"}
@@ -19,7 +19,15 @@ const WEB_ONLY_TYPES = {
19
19
  ChangeEvent: 'DOM event',
20
20
  DragEvent: 'DOM event',
21
21
  ClipboardEvent: 'DOM event',
22
+ FormEvent: 'DOM event',
23
+ TouchEvent: 'DOM event',
24
+ SyntheticEvent: 'DOM event',
22
25
  };
26
+ /** True for a DOM event type, with or without its element parameter. */
27
+ function isDomEvent(text) {
28
+ const name = /^(?:React\.)?([A-Z]\w*)(?:<[\s\S]*>)?$/.exec(text.trim())?.[1];
29
+ return name != null && WEB_ONLY_TYPES[name] === 'DOM event';
30
+ }
23
31
  const ok = (type) => ({ ok: true, type });
24
32
  const no = (reason) => ({ ok: false, reason });
25
33
  /** Splits on a separator at bracket depth zero, ignoring quoted text. */
@@ -115,10 +123,24 @@ function parseFunction(text) {
115
123
  : 'callback returns a value; only void callbacks are portable today');
116
124
  }
117
125
  const params = arrow[0].slice(1, -1).trim();
118
- const args = [];
119
- for (const param of params ? splitTop(params, ',') : []) {
126
+ const types = (params ? splitTop(params, ',') : []).map(param => {
120
127
  const match = /^([A-Za-z_$][\w$]*)\??\s*:\s*([\s\S]+)$/.exec(param);
121
- const parsed = parseDocType(match ? match[2] : param);
128
+ return match ? match[2] : param;
129
+ });
130
+ // A value callback ends with the DOM event that caused it, as in
131
+ // `(checked: boolean, e: ChangeEvent) => void`. The values are the portable
132
+ // callback; the trailing event is the web's part. A callback that carries
133
+ // only an event stays on the web.
134
+ let end = types.length;
135
+ while (end > 0 && isDomEvent(types[end - 1])) {
136
+ end--;
137
+ }
138
+ if (end === 0 && types.length > 0) {
139
+ return { ok: false, reason: 'callback argument: DOM event', eventOnly: true };
140
+ }
141
+ const args = [];
142
+ for (const type of types.slice(0, end)) {
143
+ const parsed = parseDocType(type);
122
144
  if (!parsed.ok) {
123
145
  return no(`callback argument: ${parsed.reason}`);
124
146
  }
@@ -128,8 +150,9 @@ function parseFunction(text) {
128
150
  }
129
151
  /**
130
152
  * Parses a documented type string. Supported portable forms: `string`,
131
- * `number`, `boolean`, closed string unions, arrays, plain object literals,
132
- * callbacks with portable arguments, and named types. A union of different
153
+ * `number`, `boolean`, closed string or number unions, arrays, plain object
154
+ * literals, callbacks with portable arguments (a trailing DOM event argument
155
+ * is the web's part), and named types. A union of different
133
156
  * kinds has no Swift or Kotlin form.
134
157
  */
135
158
  export function parseDocType(raw) {
@@ -146,6 +169,9 @@ export function parseDocType(raw) {
146
169
  if (members.every(m => /^'[^']*'$/.test(m))) {
147
170
  return ok({ kind: 'enum', values: members.map(m => m.slice(1, -1)) });
148
171
  }
172
+ if (members.every(m => /^-?\d+(?:\.\d+)?$/.test(m))) {
173
+ return ok({ kind: 'numberEnum', values: members.map(Number) });
174
+ }
149
175
  const webOnly = members.find(m => WEB_ONLY_TYPES[m] != null);
150
176
  if (webOnly) {
151
177
  return no(WEB_ONLY_TYPES[webOnly]);
@@ -162,6 +188,9 @@ export function parseDocType(raw) {
162
188
  if (WEB_ONLY_TYPES[t] != null) {
163
189
  return no(WEB_ONLY_TYPES[t]);
164
190
  }
191
+ if (isDomEvent(t)) {
192
+ return no('DOM event');
193
+ }
165
194
  const generic = /^(?:Readonly)?Array<([\s\S]+)>$/.exec(t);
166
195
  if (t.endsWith('[]') || generic) {
167
196
  const inner = parseDocType(generic ? generic[1] : t.slice(0, -2));
@@ -4,7 +4,10 @@ export interface ContractIssue {
4
4
  readonly rule: 'core-is-portable' | 'name-keyword' | 'name-toolkit' | 'platform-shadows-core' | 'same-name-different-meaning' | 'unknown-type';
5
5
  readonly message: string;
6
6
  }
7
- /** Why a core prop name is not allowed, or null when it is. */
8
- export declare function coreNameProblem(name: string): string | null;
7
+ /**
8
+ * Why a core prop name is not allowed, or null when it is. A toolkit name is
9
+ * allowed when the component declares it has the same meaning there.
10
+ */
11
+ export declare function coreNameProblem(name: string, sameMeaning?: boolean): string | null;
9
12
  export declare function checkContract(contract: ComponentContract): ContractIssue[];
10
13
  //# sourceMappingURL=rules.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/contract/rules.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAC,iBAAiB,EAAoB,MAAM,YAAY,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,IAAI,EACT,kBAAkB,GAClB,cAAc,GACd,cAAc,GACd,uBAAuB,GACvB,6BAA6B,GAC7B,cAAc,CAAC;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,+DAA+D;AAC/D,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgB3D;AAeD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,iBAAiB,GAAG,aAAa,EAAE,CAoE1E"}
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/contract/rules.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAC,iBAAiB,EAAoB,MAAM,YAAY,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,IAAI,EACT,kBAAkB,GAClB,cAAc,GACd,cAAc,GACd,uBAAuB,GACvB,6BAA6B,GAC7B,cAAc,CAAC;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,WAAW,UAAQ,GAClB,MAAM,GAAG,IAAI,CAgBf;AAeD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,iBAAiB,GAAG,aAAa,EAAE,CAqE1E"}
@@ -8,15 +8,18 @@
8
8
  */
9
9
  import { NATIVE_PLATFORMS } from '../platforms.js';
10
10
  import { KOTLIN_KEYWORDS, RECLAIMED, SWIFT_KEYWORDS, TOOLKIT_NAMES, } from './names.js';
11
- /** Why a core prop name is not allowed, or null when it is. */
12
- export function coreNameProblem(name) {
11
+ /**
12
+ * Why a core prop name is not allowed, or null when it is. A toolkit name is
13
+ * allowed when the component declares it has the same meaning there.
14
+ */
15
+ export function coreNameProblem(name, sameMeaning = false) {
13
16
  if (SWIFT_KEYWORDS.has(name)) {
14
17
  return `"${name}" is a Swift keyword`;
15
18
  }
16
19
  if (KOTLIN_KEYWORDS.has(name)) {
17
20
  return `"${name}" is a Kotlin keyword`;
18
21
  }
19
- if (RECLAIMED.has(name)) {
22
+ if (RECLAIMED.has(name) || sameMeaning) {
20
23
  return null;
21
24
  }
22
25
  for (const [toolkit, names] of Object.entries(TOOLKIT_NAMES)) {
@@ -46,8 +49,9 @@ export function checkContract(contract) {
46
49
  const add = (level, rule, message) => issues.push({ level, rule, message: `${contract.name}: ${message}` });
47
50
  const referenced = new Set();
48
51
  const collect = (props) => Object.values(props).forEach(spec => namedTypesIn(spec.type, referenced));
52
+ const sameMeaning = new Set(contract.sameMeaning ?? []);
49
53
  for (const name of Object.keys(contract.core)) {
50
- const problem = coreNameProblem(name);
54
+ const problem = coreNameProblem(name, sameMeaning.has(name));
51
55
  if (problem) {
52
56
  add('error', SWIFT_KEYWORDS.has(name) || KOTLIN_KEYWORDS.has(name)
53
57
  ? 'name-keyword'
@@ -16,6 +16,11 @@ export type PropType = {
16
16
  } | {
17
17
  kind: 'enum';
18
18
  values: readonly string[];
19
+ }
20
+ /** A closed set of numbers, such as a heading level or a spacing step. */
21
+ | {
22
+ kind: 'numberEnum';
23
+ values: readonly number[];
19
24
  } | {
20
25
  kind: 'array';
21
26
  of: PropType;
@@ -25,6 +30,10 @@ export type PropType = {
25
30
  } | {
26
31
  kind: 'fn';
27
32
  args: readonly PropType[];
33
+ }
34
+ /** Child Astryx components: the typed content slot (AST-082 FR4). */
35
+ | {
36
+ kind: 'content';
28
37
  } | {
29
38
  kind: 'named';
30
39
  name: string;
@@ -53,5 +62,7 @@ export interface ComponentContract {
53
62
  readonly platforms: Readonly<Partial<Record<NativePlatform, PropMap>>>;
54
63
  /** Core-doc props that stay in the web contract. */
55
64
  readonly webOnly: readonly WebOnlyProp[];
65
+ /** Core props that share a toolkit name with the same meaning (FR8). */
66
+ readonly sameMeaning?: readonly string[];
56
67
  }
57
68
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/contract/types.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,iBAAiB,CAAC;AAEpD,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAChB;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAC,GAChB;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAC,GAChB;IAAC,IAAI,EAAE,SAAS,CAAA;CAAC,GACjB;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAC,GACzC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,QAAQ,CAAA;CAAC,GAC7B;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAA;CAAC,GAC5D;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAA;CAAC,GACvC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,CAAC;AAElC,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AAEzD,sEAAsE;AACtE,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAEtE,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAClD,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,uEAAuE;IACvE,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACvE,oDAAoD;IACpD,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;CAC1C"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/contract/types.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,iBAAiB,CAAC;AAEpD,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAChB;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAC,GAChB;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAC,GAChB;IAAC,IAAI,EAAE,SAAS,CAAA;CAAC,GACjB;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAC;AAC3C,0EAA0E;GACxE;IAAC,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAC,GAC/C;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,QAAQ,CAAA;CAAC,GAC7B;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAA;CAAC,GAC5D;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAA;CAAC;AACzC,qEAAqE;GACnE;IAAC,IAAI,EAAE,SAAS,CAAA;CAAC,GACjB;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,CAAC;AAElC,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AAEzD,sEAAsE;AACtE,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAEtE,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAClD,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,uEAAuE;IACvE,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACvE,oDAAoD;IACpD,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,wEAAwE;IACxE,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C"}