@trokky/trokky 3.1.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/dist/adapters/cloudflare-d1/cloudflare-d1-adapter.d.ts +140 -0
  2. package/dist/adapters/cloudflare-d1/cloudflare-d1-adapter.d.ts.map +1 -0
  3. package/dist/adapters/cloudflare-d1/cloudflare-d1-adapter.js +853 -0
  4. package/dist/adapters/cloudflare-d1/cloudflare-d1-adapter.js.map +1 -0
  5. package/dist/adapters/cloudflare-d1/index.d.ts +5 -0
  6. package/dist/adapters/cloudflare-d1/index.d.ts.map +1 -0
  7. package/dist/adapters/cloudflare-d1/index.js +12 -0
  8. package/dist/adapters/cloudflare-d1/index.js.map +1 -0
  9. package/dist/adapters/cloudflare-d1/rate-limit-store.d.ts +46 -0
  10. package/dist/adapters/cloudflare-d1/rate-limit-store.d.ts.map +1 -0
  11. package/dist/adapters/cloudflare-d1/rate-limit-store.js +96 -0
  12. package/dist/adapters/cloudflare-d1/rate-limit-store.js.map +1 -0
  13. package/dist/adapters/cloudflare-d1/types.d.ts +69 -0
  14. package/dist/adapters/cloudflare-d1/types.d.ts.map +1 -0
  15. package/dist/adapters/cloudflare-d1/types.js +2 -0
  16. package/dist/adapters/cloudflare-d1/types.js.map +1 -0
  17. package/dist/adapters/cloudflare-r2/cloudflare-r2-adapter.d.ts +86 -0
  18. package/dist/adapters/cloudflare-r2/cloudflare-r2-adapter.d.ts.map +1 -0
  19. package/dist/adapters/cloudflare-r2/cloudflare-r2-adapter.js +493 -0
  20. package/dist/adapters/cloudflare-r2/cloudflare-r2-adapter.js.map +1 -0
  21. package/dist/adapters/cloudflare-r2/index.d.ts +3 -0
  22. package/dist/adapters/cloudflare-r2/index.d.ts.map +1 -0
  23. package/dist/adapters/cloudflare-r2/index.js +11 -0
  24. package/dist/adapters/cloudflare-r2/index.js.map +1 -0
  25. package/dist/adapters/cloudflare-r2/types.d.ts +43 -0
  26. package/dist/adapters/cloudflare-r2/types.d.ts.map +1 -0
  27. package/dist/adapters/cloudflare-r2/types.js +2 -0
  28. package/dist/adapters/cloudflare-r2/types.js.map +1 -0
  29. package/dist/adapters/filesystem-data/filesystem-data-adapter.d.ts +9 -0
  30. package/dist/adapters/filesystem-data/filesystem-data-adapter.d.ts.map +1 -1
  31. package/dist/adapters/filesystem-data/filesystem-data-adapter.js +28 -0
  32. package/dist/adapters/filesystem-data/filesystem-data-adapter.js.map +1 -1
  33. package/dist/adapters/postgres-data/postgres-data-adapter.d.ts +9 -0
  34. package/dist/adapters/postgres-data/postgres-data-adapter.d.ts.map +1 -1
  35. package/dist/adapters/postgres-data/postgres-data-adapter.js +59 -0
  36. package/dist/adapters/postgres-data/postgres-data-adapter.js.map +1 -1
  37. package/dist/core/core/engine.d.ts +10 -0
  38. package/dist/core/core/engine.d.ts.map +1 -1
  39. package/dist/core/core/engine.js +16 -2
  40. package/dist/core/core/engine.js.map +1 -1
  41. package/dist/core/media/image-processor.d.ts.map +1 -1
  42. package/dist/core/media/image-processor.js +5 -13
  43. package/dist/core/media/image-processor.js.map +1 -1
  44. package/dist/core/media/processors/sharp.d.ts.map +1 -1
  45. package/dist/core/media/processors/sharp.js +13 -2
  46. package/dist/core/media/processors/sharp.js.map +1 -1
  47. package/dist/core/media/processors/types.d.ts +1 -1
  48. package/dist/core/media/processors/types.d.ts.map +1 -1
  49. package/dist/core/security/rate-limit-store.d.ts +56 -0
  50. package/dist/core/security/rate-limit-store.d.ts.map +1 -0
  51. package/dist/core/security/rate-limit-store.js +55 -0
  52. package/dist/core/security/rate-limit-store.js.map +1 -0
  53. package/dist/core/security/rate-limiter.d.ts +39 -2
  54. package/dist/core/security/rate-limiter.d.ts.map +1 -1
  55. package/dist/core/security/rate-limiter.js +52 -20
  56. package/dist/core/security/rate-limiter.js.map +1 -1
  57. package/dist/core/services/media-service.d.ts +34 -0
  58. package/dist/core/services/media-service.d.ts.map +1 -1
  59. package/dist/core/services/media-service.js +172 -120
  60. package/dist/core/services/media-service.js.map +1 -1
  61. package/dist/core/services/user-service.d.ts +42 -0
  62. package/dist/core/services/user-service.d.ts.map +1 -1
  63. package/dist/core/services/user-service.js +114 -1
  64. package/dist/core/services/user-service.js.map +1 -1
  65. package/dist/core/types/storage-adapters.d.ts +18 -0
  66. package/dist/core/types/storage-adapters.d.ts.map +1 -1
  67. package/dist/core/utils/retry.d.ts +45 -0
  68. package/dist/core/utils/retry.d.ts.map +1 -0
  69. package/dist/core/utils/retry.js +47 -0
  70. package/dist/core/utils/retry.js.map +1 -0
  71. package/dist/i18n/config.d.ts +32 -0
  72. package/dist/i18n/config.d.ts.map +1 -1
  73. package/dist/i18n/locales/en/auth.json +16 -0
  74. package/dist/i18n/locales/fr/auth.json +16 -0
  75. package/dist/integrations/workers/adapter.d.ts +28 -0
  76. package/dist/integrations/workers/adapter.d.ts.map +1 -0
  77. package/dist/integrations/workers/adapter.js +111 -0
  78. package/dist/integrations/workers/adapter.js.map +1 -0
  79. package/dist/integrations/workers/index.d.ts +22 -0
  80. package/dist/integrations/workers/index.d.ts.map +1 -0
  81. package/dist/integrations/workers/index.js +60 -0
  82. package/dist/integrations/workers/index.js.map +1 -0
  83. package/dist/routes/auth/auth-flow-store.d.ts +17 -0
  84. package/dist/routes/auth/auth-flow-store.d.ts.map +1 -1
  85. package/dist/routes/auth/auth-flow-store.js +27 -0
  86. package/dist/routes/auth/auth-flow-store.js.map +1 -1
  87. package/dist/routes/auth/oauth.d.ts.map +1 -1
  88. package/dist/routes/auth/oauth.js +5 -12
  89. package/dist/routes/auth/oauth.js.map +1 -1
  90. package/dist/routes/auth/passkey.d.ts.map +1 -1
  91. package/dist/routes/auth/passkey.js +5 -8
  92. package/dist/routes/auth/passkey.js.map +1 -1
  93. package/dist/routes/handlers/auth.d.ts +14 -0
  94. package/dist/routes/handlers/auth.d.ts.map +1 -1
  95. package/dist/routes/handlers/auth.js +55 -0
  96. package/dist/routes/handlers/auth.js.map +1 -1
  97. package/dist/structure/validation/schemas.d.ts +60 -60
  98. package/package.json +20 -1
  99. package/dist/core/media/processors/cloudflare-images.d.ts +0 -83
  100. package/dist/core/media/processors/cloudflare-images.d.ts.map +0 -1
  101. package/dist/core/media/processors/cloudflare-images.js +0 -241
  102. package/dist/core/media/processors/cloudflare-images.js.map +0 -1
  103. package/dist/core/media/processors/cloudflare-transform-store.d.ts +0 -127
  104. package/dist/core/media/processors/cloudflare-transform-store.d.ts.map +0 -1
  105. package/dist/core/media/processors/cloudflare-transform-store.js +0 -237
  106. package/dist/core/media/processors/cloudflare-transform-store.js.map +0 -1
  107. package/dist/core/media/processors/cloudflare-transformations.d.ts +0 -81
  108. package/dist/core/media/processors/cloudflare-transformations.d.ts.map +0 -1
  109. package/dist/core/media/processors/cloudflare-transformations.js +0 -144
  110. package/dist/core/media/processors/cloudflare-transformations.js.map +0 -1
  111. package/dist/core/media/processors/workers-images.d.ts +0 -112
  112. package/dist/core/media/processors/workers-images.d.ts.map +0 -1
  113. package/dist/core/media/processors/workers-images.js +0 -257
  114. package/dist/core/media/processors/workers-images.js.map +0 -1
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Cloudflare D1 data storage adapter.
3
+ *
4
+ * D1 is SQLite, which differs from Postgres in ways that are invisible until a
5
+ * conformance test fails, so the choices below are deliberate:
6
+ *
7
+ * - **Timestamps are generated in JS, never by SQL.** SQLite's `CURRENT_TIMESTAMP`
8
+ * has one-second resolution; the suite orders fixtures 20ms apart, so rows would
9
+ * tie and sort arbitrarily.
10
+ * - **Document payloads are one JSON TEXT blob.** Shredding fields into columns
11
+ * loses the distinction between `0`, `false`, `''`, `null` and absent, all of
12
+ * which must round-trip byte-identically.
13
+ * - **Filters compare value *and* `json_type`.** `json_extract` collapses JSON
14
+ * booleans to 0/1, so a naive equality makes `false` match a stored `0`.
15
+ * - **Sorts use `json_extract`**, which yields real SQL numbers; the text
16
+ * accessors would sort 13 before 2.
17
+ * - **There is no `beginTransaction`.** D1 has no interactive transactions, and
18
+ * the interface allows omitting it. The three places that need atomicity each
19
+ * do it in one statement: the document upsert, `saveUserIf`'s conditional
20
+ * UPDATE, and `consumeAuthFlowState`'s `DELETE … RETURNING`.
21
+ */
22
+ import type { AppToken, AuditContext, CreateAppTokenData, CreateUserData, Document, DocumentData, ListOptions, UpdateUserData, User } from '../../core/types/index.js';
23
+ import type { AuthFlowState, DataStorageAdapter, SettingsConfig } from '../../core/types/storage-adapters.js';
24
+ import type { CloudflareD1AdapterConfig } from './types.js';
25
+ export declare class CloudflareD1Adapter implements DataStorageAdapter {
26
+ private readonly db;
27
+ private readonly tablePrefix;
28
+ private readonly autoMigrate;
29
+ private readonly logger;
30
+ private migrated;
31
+ private migrationPromise;
32
+ /** D1 rejects a single value over ~2MB, well below the 10MB other adapters allow. */
33
+ private readonly MAX_DOCUMENT_SIZE;
34
+ private readonly MAX_LIST_LIMIT;
35
+ constructor(config: CloudflareD1AdapterConfig);
36
+ private table;
37
+ private now;
38
+ /** Migrations run once; concurrent callers await the same promise. */
39
+ private ready;
40
+ /**
41
+ * Create the schema. No DEFAULTs on the JSON columns: a default of '{}' would
42
+ * turn an absent value into an empty object on read, where `undefined` is
43
+ * required.
44
+ */
45
+ migrate(): Promise<void>;
46
+ close(): Promise<void>;
47
+ healthCheck(): Promise<boolean>;
48
+ private mapRowToDocument;
49
+ getDocument(collection: string, id: string): Promise<Document | null>;
50
+ saveDocument(collection: string, id: string, data: DocumentData, auditContext?: AuditContext): Promise<Document>;
51
+ deleteDocument(collection: string, id: string): Promise<void>;
52
+ /**
53
+ * Filter clauses shared by listDocuments and countDocuments so the two can
54
+ * never disagree. A data-field comparison checks `json_type` as well as the
55
+ * value: json_extract turns JSON true/false into 1/0, so value alone would
56
+ * make `false` match a stored `0`.
57
+ */
58
+ private buildFilterClauses;
59
+ /**
60
+ * ORDER BY terms. Data fields go through json_extract, which yields a real SQL
61
+ * number, so 2 sorts before 13; the text accessors would not.
62
+ */
63
+ private buildSortClause;
64
+ listDocuments(collection: string, options?: ListOptions): Promise<Document[]>;
65
+ countDocuments(collection: string, filter?: Record<string, unknown>): Promise<number>;
66
+ documentExists(collection: string, id: string): Promise<boolean>;
67
+ private mapRowToUser;
68
+ getUser(id: string): Promise<User | null>;
69
+ /**
70
+ * Build the SET list from the keys actually present. A key holding `null`
71
+ * clears the column; a key that is absent, or present as `undefined`, leaves
72
+ * it alone. COALESCE cannot express that difference.
73
+ */
74
+ private buildUserAssignments;
75
+ saveUser(id: string, userData: CreateUserData | Partial<UpdateUserData>): Promise<User>;
76
+ /** The bind list for a user INSERT, shared so the two insert paths cannot drift. */
77
+ private userInsertValues;
78
+ /**
79
+ * Create the first user, atomically. SQLite serialises writers, so a single
80
+ * `INSERT ... SELECT ... WHERE NOT EXISTS` is the check and the write under one
81
+ * lock: of two concurrent calls, exactly one inserts and the other gets no row.
82
+ */
83
+ createFirstUser(id: string, userData: CreateUserData): Promise<User | null>;
84
+ /**
85
+ * Compare-and-swap in one statement. SQLite makes a single UPDATE atomic, so
86
+ * no transaction is needed: the WHERE clause is the comparison, and RETURNING
87
+ * proves whether it matched.
88
+ */
89
+ saveUserIf(id: string, userData: Partial<UpdateUserData>, condition: {
90
+ passwordHash: string;
91
+ }): Promise<User | null>;
92
+ listUsers(options?: {
93
+ role?: string;
94
+ isActive?: boolean;
95
+ limit?: number;
96
+ offset?: number;
97
+ }): Promise<User[]>;
98
+ deleteUser(id: string): Promise<void>;
99
+ private findUserBy;
100
+ getUserByUsername(username: string): Promise<User | null>;
101
+ getUserByEmail(email: string): Promise<User | null>;
102
+ isUsernameAvailable(username: string): Promise<boolean>;
103
+ isEmailAvailable(email: string): Promise<boolean>;
104
+ getUserByOAuthProvider(provider: string, providerId: string): Promise<User | null>;
105
+ getUserByPasskeyCredentialId(credentialId: string): Promise<User | null>;
106
+ private mapRowToAppToken;
107
+ getAppToken(id: string): Promise<AppToken | null>;
108
+ getAppTokenByHash(hash: string): Promise<AppToken | null>;
109
+ saveAppToken(id: string, data: CreateAppTokenData | Partial<AppToken>): Promise<AppToken>;
110
+ listAppTokens(options?: {
111
+ createdBy?: string;
112
+ isActive?: boolean;
113
+ limit?: number;
114
+ offset?: number;
115
+ }): Promise<AppToken[]>;
116
+ deleteAppToken(id: string): Promise<void>;
117
+ saveAuthFlowState(state: AuthFlowState): Promise<void>;
118
+ /**
119
+ * One statement, so two concurrent callers cannot both win. Kind and expiry
120
+ * are part of the WHERE clause: presenting another flow's id neither returns
121
+ * it nor destroys it.
122
+ */
123
+ consumeAuthFlowState(id: string, kind: AuthFlowState['kind']): Promise<AuthFlowState | null>;
124
+ deleteExpiredAuthFlowStates(): Promise<number>;
125
+ getSettings(): Promise<SettingsConfig | null>;
126
+ saveSettings(settings: SettingsConfig): Promise<void>;
127
+ getStorageInfo(): Promise<{
128
+ [key: string]: unknown;
129
+ collections: string[];
130
+ documentCount: number;
131
+ userCount: number;
132
+ tokenCount: number;
133
+ storageSize?: number;
134
+ }>;
135
+ /** Not implemented: D1 has no interactive transactions. */
136
+ readonly beginTransaction: undefined;
137
+ /** Escape hatch for callers that need raw SQL, e.g. migrations. */
138
+ execute<T = unknown>(sql: string, params?: unknown[]): Promise<T[]>;
139
+ }
140
+ //# sourceMappingURL=cloudflare-d1-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-d1-adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/cloudflare-d1/cloudflare-d1-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,cAAc,EACd,IAAI,EACL,MAAM,2BAA2B,CAAA;AAClC,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,cAAc,EACf,MAAM,sCAAsC,CAAA;AAC7C,OAAO,KAAK,EACV,yBAAyB,EAK1B,MAAM,YAAY,CAAA;AA0FnB,qBAAa,mBAAoB,YAAW,kBAAkB;IAC5D,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAY;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,gBAAgB,CAA6B;IAErD,qFAAqF;IACrF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAY;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAO;gBAE1B,MAAM,EAAE,yBAAyB;IAW7C,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,GAAG;IAIX,sEAAsE;YACxD,KAAK;IAoBnB;;;;OAIG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAyExB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAa5C,OAAO,CAAC,gBAAgB;IAqBX,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAarE,YAAY,CACvB,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,YAAY,EAClB,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,QAAQ,CAAC;IA+CP,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAe1E;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAkC1B;;;OAGG;IACH,OAAO,CAAC,eAAe;IAmCV,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAoBjF,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAarF,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAe7E,OAAO,CAAC,YAAY;IAwBP,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAStD;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAuBf,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAkCpG,oFAAoF;IACpF,OAAO,CAAC,gBAAgB;IAsBxB;;;;OAIG;IACU,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAmBxF;;;;OAIG;IACU,UAAU,CACrB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,EACjC,SAAS,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,GAClC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAiBV,SAAS,CACpB,OAAO,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GACnF,OAAO,CAAC,IAAI,EAAE,CAAC;IA0BL,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAQpC,UAAU;IAYX,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAIzD,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAInD,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIvD,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIjD,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAelF,4BAA4B,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAoBrF,OAAO,CAAC,gBAAgB;IAmBX,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IASjD,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAmBzD,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC;IA4DzF,aAAa,CACxB,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GACxF,OAAO,CAAC,QAAQ,EAAE,CAAC;IAuBT,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUzC,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAcnE;;;;OAIG;IACU,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAoB5F,2BAA2B,IAAI,OAAO,CAAC,MAAM,CAAC;IAW9C,WAAW,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAQ7C,YAAY,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAWrD,cAAc,IAAI,OAAO,CAAC;QACrC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;QACtB,WAAW,EAAE,MAAM,EAAE,CAAA;QACrB,aAAa,EAAE,MAAM,CAAA;QACrB,SAAS,EAAE,MAAM,CAAA;QACjB,UAAU,EAAE,MAAM,CAAA;QAClB,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB,CAAC;IAqBF,2DAA2D;IAC3D,SAAgB,gBAAgB,YAAY;IAE5C,mEAAmE;IACtD,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;CAQrF"}