sonamu 0.10.3 → 0.10.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/database/puri.d.ts +4 -1
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +18 -1
- package/dist/database/puri.types.d.ts +12 -1
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +1 -1
- package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
- package/dist/migration/postgresql-schema-reader.js +2 -3
- package/dist/naite/naite-reporter.d.ts.map +1 -1
- package/dist/naite/naite-reporter.js +10 -2
- package/dist/template/implementations/generated.template.d.ts.map +1 -1
- package/dist/template/implementations/generated.template.js +8 -3
- package/package.json +3 -3
- package/src/database/__tests__/puri.test.ts +66 -0
- package/src/database/puri.ts +40 -0
- package/src/database/puri.types.test-d.ts +115 -1
- package/src/database/puri.types.ts +19 -0
- package/src/migration/postgresql-schema-reader.ts +1 -2
- package/src/naite/naite-reporter.ts +10 -1
- package/src/skills/sonamu/puri.md +28 -0
- package/src/template/__tests__/generated.template.search-text.test.ts +17 -2
- package/src/template/implementations/generated.template.ts +15 -1
|
@@ -157,12 +157,17 @@ var Template__generated = class extends Template {
|
|
|
157
157
|
*/
|
|
158
158
|
const hasVectorColumns = entity.props.filter((prop) => prop.type === "vector" || prop.type === "vector[]").map((prop) => prop.name);
|
|
159
159
|
/**
|
|
160
|
+
* JSON props
|
|
161
|
+
* - json 타입인 컬럼
|
|
162
|
+
*/
|
|
163
|
+
const jsonColumns = entity.props.filter((prop) => prop.type === "json").map((prop) => prop.name);
|
|
164
|
+
/**
|
|
160
165
|
* generated props
|
|
161
166
|
* - generated 속성이 있는 컬럼 (INSERT/UPDATE 시 값 제공 불가)
|
|
162
167
|
*/
|
|
163
168
|
const generatedColumns = entity.props.filter((prop) => prop.type !== "relation" && (prop.generated !== void 0 || prop.type === "searchText")).map((prop) => prop.name);
|
|
164
|
-
const hasMetadata = fulltextColumns.length > 0 || virtualProps.length > 0 || virtualQueryProps.length > 0 || hasDefaultColumns.length > 0 || generatedColumns.length > 0 || hasVectorColumns.length > 0;
|
|
165
|
-
const lines = [`export const ${schemaName} = ${schemaBody};`, `export type ${schemaName} = z.infer<typeof ${schemaName}>` + (hasMetadata ? ` & {${(fulltextColumns.length > 0 ? `readonly __fulltext__: readonly [${fulltextColumns.map((col) => `"${col}"`).join(", ")}],` : "") + (virtualProps.length > 0 ? `readonly __virtual__: readonly [${virtualProps.map((prop) => `"${prop}"`).join(", ")}],` : "") + (virtualQueryProps.length > 0 ? `readonly __virtual_query__: readonly [${virtualQueryProps.map((prop) => `"${prop}"`).join(", ")}],` : "") + (hasDefaultColumns.length > 0 ? `readonly __hasDefault__: readonly [${hasDefaultColumns.map((col) => `"${col}"`).join(", ")}],` : "") + (generatedColumns.length > 0 ? `readonly __generated__: readonly [${generatedColumns.map((col) => `"${col}"`).join(", ")}],` : "") + (hasVectorColumns.length > 0 ? `readonly __vector__: readonly [${hasVectorColumns.map((col) => `"${col}"`).join(", ")}],` : "")}}` : "") + ";"];
|
|
169
|
+
const hasMetadata = fulltextColumns.length > 0 || virtualProps.length > 0 || virtualQueryProps.length > 0 || hasDefaultColumns.length > 0 || generatedColumns.length > 0 || hasVectorColumns.length > 0 || jsonColumns.length > 0;
|
|
170
|
+
const lines = [`export const ${schemaName} = ${schemaBody};`, `export type ${schemaName} = z.infer<typeof ${schemaName}>` + (hasMetadata ? ` & {${(fulltextColumns.length > 0 ? `readonly __fulltext__: readonly [${fulltextColumns.map((col) => `"${col}"`).join(", ")}],` : "") + (virtualProps.length > 0 ? `readonly __virtual__: readonly [${virtualProps.map((prop) => `"${prop}"`).join(", ")}],` : "") + (virtualQueryProps.length > 0 ? `readonly __virtual_query__: readonly [${virtualQueryProps.map((prop) => `"${prop}"`).join(", ")}],` : "") + (hasDefaultColumns.length > 0 ? `readonly __hasDefault__: readonly [${hasDefaultColumns.map((col) => `"${col}"`).join(", ")}],` : "") + (generatedColumns.length > 0 ? `readonly __generated__: readonly [${generatedColumns.map((col) => `"${col}"`).join(", ")}],` : "") + (hasVectorColumns.length > 0 ? `readonly __vector__: readonly [${hasVectorColumns.map((col) => `"${col}"`).join(", ")}],` : "") + (jsonColumns.length > 0 ? `readonly __json__: readonly [${jsonColumns.map((col) => `"${col}"`).join(", ")}],` : "")}}` : "") + ";"];
|
|
166
171
|
return {
|
|
167
172
|
label: `BaseSchema: ${entity.id}`,
|
|
168
173
|
importKeys,
|
|
@@ -239,4 +244,4 @@ z.object({
|
|
|
239
244
|
//#endregion
|
|
240
245
|
export { Template__generated };
|
|
241
246
|
|
|
242
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGVkLnRlbXBsYXRlLmpzIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZW1wbGF0ZS9pbXBsZW1lbnRhdGlvbnMvZ2VuZXJhdGVkLnRlbXBsYXRlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuXG5pbXBvcnQgeyB1bmlxdWUgfSBmcm9tIFwicmFkYXNoaVwiO1xuXG5pbXBvcnQgeyBTb25hbXUgfSBmcm9tIFwiLi4vLi4vYXBpXCI7XG5pbXBvcnQgeyB0eXBlIEVudGl0eSB9IGZyb20gXCIuLi8uLi9lbnRpdHkvZW50aXR5XCI7XG5pbXBvcnQgeyBFbnRpdHlNYW5hZ2VyIH0gZnJvbSBcIi4uLy4uL2VudGl0eS9lbnRpdHktbWFuYWdlclwiO1xuaW1wb3J0IHsgTmFpdGUgfSBmcm9tIFwiLi4vLi4vbmFpdGUvbmFpdGVcIjtcbmltcG9ydCB7IGlzVmlydHVhbENvZGVQcm9wLCBpc1ZpcnR1YWxRdWVyeVByb3AgfSBmcm9tIFwiLi4vLi4vdHlwZXMvdHlwZXNcIjtcbmltcG9ydCB7IHR5cGUgRW50aXR5SW5kZXgsIHR5cGUgRW50aXR5UHJvcE5vZGUgfSBmcm9tIFwiLi4vLi4vdHlwZXMvdHlwZXNcIjtcbmltcG9ydCB7IG5vbk51bGxhYmxlIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3V0aWxzXCI7XG5pbXBvcnQgeyBUZW1wbGF0ZSB9IGZyb20gXCIuLi90ZW1wbGF0ZVwiO1xuaW1wb3J0IHsgQlVJTFRfSU5fVFlQRVMsIHByb3BOb2RlVG9ab2RUeXBlRGVmLCB6b2RUeXBlVG9ab2RDb2RlIH0gZnJvbSBcIi4uL3pvZC1jb252ZXJ0ZXJcIjtcblxuZXhwb3J0IHR5cGUgU291cmNlQ29kZSA9IHtcbiAgbGFiZWw6IHN0cmluZztcbiAgbGluZXM6IHN0cmluZ1tdO1xuICBpbXBvcnRLZXlzOiBzdHJpbmdbXTtcbn07XG5leHBvcnQgY2xhc3MgVGVtcGxhdGVfX2dlbmVyYXRlZCBleHRlbmRzIFRlbXBsYXRlIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoXCJnZW5lcmF0ZWRcIik7XG4gIH1cblxuICBnZXRUYXJnZXRBbmRQYXRoKCkge1xuICAgIGNvbnN0IHsgZGlyIH0gPSBTb25hbXUuY29uZmlnLmFwaTtcbiAgICByZXR1cm4ge1xuICAgICAgdGFyZ2V0OiBgJHtkaXJ9L3NyYy9hcHBsaWNhdGlvbmAsXG4gICAgICBwYXRoOiBgc29uYW11LmdlbmVyYXRlZC50c2AsXG4gICAgfTtcbiAgfVxuICByZW5kZXIoKSB7XG4gICAgY29uc3QgZW50aXR5SWRzID0gRW50aXR5TWFuYWdlci5nZXRBbGxJZHMoKTtcbiAgICBjb25zdCBlbnRpdGllcyA9IGVudGl0eUlkcy5tYXAoKGlkKSA9PiBFbnRpdHlNYW5hZ2VyLmdldChpZCkpO1xuXG4gICAgLy8g7KCE7LK0IFNvdXJjZUNvZGUg7IOd7ISxXG4gICAgY29uc3Qgc291cmNlQ29kZXMgPSBlbnRpdGllcy5mbGF0TWFwKChlbnRpdHkpID0+IHtcbiAgICAgIHJldHVybiBbXG4gICAgICAgIHRoaXMuZ2V0RW51bXNTb3VyY2VDb2RlKGVudGl0eSksXG4gICAgICAgIHRoaXMuZ2V0QmFzZVNjaGVtYVNvdXJjZUNvZGUoZW50aXR5KSxcbiAgICAgICAgdGhpcy5nZXRCYXNlTGlzdFBhcmFtc1NvdXJjZUNvZGUoZW50aXR5KSxcbiAgICAgICAgdGhpcy5nZXRTdWJzZXRTb3VyY2VDb2RlKGVudGl0eSksXG4gICAgICBdLmZpbHRlcihub25OdWxsYWJsZSk7XG4gICAgfSk7XG4gICAgTmFpdGUudChcIlRlbXBsYXRlX19nZW5lcmF0ZWQ6c291cmNlQ29kZXNcIiwgc291cmNlQ29kZXMpO1xuXG4gICAgLy8gU29ydFxuICAgIGNvbnN0IExBQkVMX0tFWV9PUkRFUiA9IFtcIkVudW1zXCIsIFwiQmFzZVNjaGVtYVwiLCBcIkJhc2VMaXN0UGFyYW1zXCIsIFwiU3Vic2V0c1wiLCBcIlN1YnNldFF1ZXJpZXNcIl07XG4gICAgc291cmNlQ29kZXMuc29ydCgoYSwgYikgPT4ge1xuICAgICAgY29uc3QgW2FLZXldID0gYS5sYWJlbC5zcGxpdChcIjpcIik7XG4gICAgICBjb25zdCBbYktleV0gPSBiLmxhYmVsLnNwbGl0KFwiOlwiKTtcbiAgICAgIGNvbnN0IGFJbmRleCA9IExBQkVMX0tFWV9PUkRFUi5pbmRleE9mKGFLZXkpO1xuICAgICAgY29uc3QgYkluZGV4ID0gTEFCRUxfS0VZX09SREVSLmluZGV4T2YoYktleSk7XG4gICAgICBpZiAoYUluZGV4ID4gYkluZGV4KSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfSBlbHNlIGlmIChhSW5kZXggPCBiSW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBjb25zdCBzb3VyY2VDb2RlID0gc291cmNlQ29kZXMucmVkdWNlKFxuICAgICAgKHJlc3VsdCwgdHMpID0+IHtcbiAgICAgICAgaWYgKHRzID09PSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGxpbmVzOiBbLi4ucmVzdWx0LmxpbmVzLCBgLy8gJHt0cy5sYWJlbH1gLCAuLi50cy5saW5lcywgXCJcIl0sXG4gICAgICAgICAgaW1wb3J0S2V5czogdW5pcXVlKFsuLi5yZXN1bHQuaW1wb3J0S2V5cywgLi4udHMuaW1wb3J0S2V5c10udG9Tb3J0ZWQoKSksXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBsaW5lczogW10sXG4gICAgICAgIGltcG9ydEtleXM6IFtdLFxuICAgICAgfSBhcyBPbWl0PFNvdXJjZUNvZGUsIFwibGFiZWxcIj4sXG4gICAgKTtcblxuICAgIC8vIC50eXBlcy50c+ydmCDtg4DsnoXsnYQg7LC47KGw7ZWY64qUIOqyveyasCDsiJztmZjssLjsobAo7IOB7Zi47LC47KGwKeqwgCDrsJzsg53tlZjrr4DroZwg7YOA7J6F7J2EIOqwgOyguOyZgCDsnbjrnbzsnbgg7LKY66asXG4gICAgY29uc3QgYWxsVHlwZUtleXMgPSBlbnRpdGllcy5mbGF0TWFwKChlbnRpdHkpID0+IE9iamVjdC5rZXlzKGVudGl0eS50eXBlcykpO1xuICAgIGNvbnN0IGNkSW1wb3J0S2V5cyA9IHNvdXJjZUNvZGUuaW1wb3J0S2V5cy5maWx0ZXIoKGltcG9ydEtleSkgPT5cbiAgICAgIGFsbFR5cGVLZXlzLmluY2x1ZGVzKGltcG9ydEtleSksXG4gICAgKTtcbiAgICBpZiAoY2RJbXBvcnRLZXlzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IGN1c3RvbVNjYWxhckxpbmVzID0gY2RJbXBvcnRLZXlzLmZsYXRNYXAoKGltcG9ydEtleSkgPT4ge1xuICAgICAgICBjb25zdCBlbnRpdHkgPSBlbnRpdGllcy5maW5kKChlbnRpdHkpID0+IGVudGl0eS50eXBlc1tpbXBvcnRLZXldKTtcbiAgICAgICAgaWYgKCFlbnRpdHkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFpvZFR5cGUgbm90IGZvdW5kICR7aW1wb3J0S2V5fWApO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHpvZFR5cGUgPSBlbnRpdHkudHlwZXNbaW1wb3J0S2V5XTtcbiAgICAgICAgYXNzZXJ0KHpvZFR5cGUpO1xuXG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgYC8vIEN1c3RvbVNjYWxhcjogJHtpbXBvcnRLZXl9YCxcbiAgICAgICAgICBgY29uc3QgJHtpbXBvcnRLZXl9ID0gJHt6b2RUeXBlVG9ab2RDb2RlKHpvZFR5cGUsIHNvdXJjZUNvZGUuaW1wb3J0S2V5cyl9O2AsXG4gICAgICAgICAgYHR5cGUgJHtpbXBvcnRLZXl9ID0gei5pbmZlcjx0eXBlb2YgJHtpbXBvcnRLZXl9PmAsXG4gICAgICAgICAgXCJcIixcbiAgICAgICAgXTtcbiAgICAgIH0pO1xuICAgICAgc291cmNlQ29kZS5saW5lcyA9IFsuLi5jdXN0b21TY2FsYXJMaW5lcywgLi4uc291cmNlQ29kZS5saW5lc107XG4gICAgICBzb3VyY2VDb2RlLmltcG9ydEtleXMgPSB1bmlxdWUoXG4gICAgICAgIHNvdXJjZUNvZGUuaW1wb3J0S2V5cy5maWx0ZXIoKGltcG9ydEtleSkgPT4gIWNkSW1wb3J0S2V5cy5pbmNsdWRlcyhpbXBvcnRLZXkpKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgYm9keSA9IHNvdXJjZUNvZGUubGluZXMuam9pbihcIlxcblwiKTtcbiAgICBOYWl0ZS50KFwiVGVtcGxhdGVfX2dlbmVyYXRlZDpib2R5XCIsIGJvZHkpO1xuXG4gICAgLy8gaW1wb3J0XG4gICAgLy8gc291cmNlQ29kZS5pbXBvcnRLZXlz7JeQIOuCtOyepSDtg4DsnoXsnZgg7Iqk7YKk66eI6rCAIOyeiOycvOuptCBzb25hbXUgaW1wb3J07JeQIOy2lOqwgFxuICAgIGNvbnN0IGJ1aWx0SW5TY2hlbWFOYW1lcyA9IE9iamVjdC52YWx1ZXMoQlVJTFRfSU5fVFlQRVMpLm1hcChcbiAgICAgIChpbmZvKSA9PiBpbmZvLnNjaGVtYU5hbWUgYXMgc3RyaW5nLFxuICAgICk7XG4gICAgY29uc3QgYnVpbHRJblNjaGVtYXMgPSBzb3VyY2VDb2RlLmltcG9ydEtleXMuZmlsdGVyKChrZXkpID0+IGJ1aWx0SW5TY2hlbWFOYW1lcy5pbmNsdWRlcyhrZXkpKTtcbiAgICBjb25zdCBzb25hbXVJbXBvcnRzID0gW1xuICAgICAgXCJ6QXJyYXlhYmxlXCIsXG4gICAgICBcIlNRTERhdGVUaW1lU3RyaW5nXCIsXG4gICAgICBcIlN1YnNldFF1ZXJ5XCIsXG4gICAgICBcIlNvbmFtdVF1ZXJ5TW9kZVwiLFxuICAgICAgXCJBcHBseVNvbmFtdUZpbHRlclwiLFxuICAgICAgLi4uYnVpbHRJblNjaGVtYXMsXG4gICAgXS5maWx0ZXIoKG1vZCkgPT4gYm9keS5pbmNsdWRlcyhtb2QpKTtcblxuICAgIHJldHVybiB7XG4gICAgICAuLi50aGlzLmdldFRhcmdldEFuZFBhdGgoKSxcbiAgICAgIGJvZHksXG4gICAgICBpbXBvcnRLZXlzOiBzb3VyY2VDb2RlLmltcG9ydEtleXMsXG4gICAgICBjdXN0b21IZWFkZXJzOiBbXG4gICAgICAgIFwiLyoqXCIsXG4gICAgICAgIFwiICogQGdlbmVyYXRlZFwiLFxuICAgICAgICBcIiAqIOyngeygkSDsiJjsoJXtlZjsp4Ag66eI7IS47JqULlwiLFxuICAgICAgICBcIiAqL1wiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIi8qIG94bGludC1kaXNhYmxlICovXCIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIGBpbXBvcnQgeyB6IH0gZnJvbSAnem9kJztgLFxuICAgICAgICBgaW1wb3J0IHsgJHtzb25hbXVJbXBvcnRzLmpvaW4oXCIsXCIpfSB9IGZyb20gXCJzb25hbXVcIjtgLFxuICAgICAgXSxcbiAgICB9O1xuICB9XG5cbiAgZ2V0RW51bXNTb3VyY2VDb2RlKGVudGl0eTogRW50aXR5KTogU291cmNlQ29kZSB8IG51bGwge1xuICAgIGlmIChPYmplY3Qua2V5cyhlbnRpdHkuZW51bUxhYmVscykubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGxhYmVsOiBgRW51bXM6ICR7ZW50aXR5LmlkfWAsXG4gICAgICBsaW5lczogT2JqZWN0LmVudHJpZXMoZW50aXR5LmVudW1MYWJlbHMpXG4gICAgICAgIC5maWx0ZXIoKFtfLCBlbnVtTGFiZWxdKSA9PiBPYmplY3Qua2V5cyhlbnVtTGFiZWwpLmxlbmd0aCA+IDApXG4gICAgICAgIC5mbGF0TWFwKChbZW51bUlkLCBlbnVtTGFiZWxdKSA9PiBbXG4gICAgICAgICAgYGV4cG9ydCBjb25zdCAke2VudW1JZH0gPSB6LmVudW0oWyR7T2JqZWN0LmtleXMoZW51bUxhYmVsKS5tYXAoXG4gICAgICAgICAgICAoZWwpID0+IGBcIiR7ZWx9XCJgLFxuICAgICAgICAgICl9XSkuZGVzY3JpYmUoXCIke2VudW1JZH1cIik7YCxcbiAgICAgICAgICBgZXhwb3J0IHR5cGUgJHtlbnVtSWR9ID0gei5pbmZlcjx0eXBlb2YgJHtlbnVtSWR9PjtgLFxuICAgICAgICAgIGBleHBvcnQgY29uc3QgJHtlbnVtSWR9TGFiZWwgPSAke0pTT04uc3RyaW5naWZ5KGVudW1MYWJlbCl9O2AsXG4gICAgICAgIF0pLFxuICAgICAgaW1wb3J0S2V5czogW10sXG4gICAgfTtcbiAgfVxuXG4gIGdldEJhc2VTY2hlbWFTb3VyY2VDb2RlKGVudGl0eTogRW50aXR5LCBpbXBvcnRLZXlzOiBzdHJpbmdbXSA9IFtdKTogU291cmNlQ29kZSB7XG4gICAgY29uc3Qgc2NoZW1hTmFtZSA9IGAke2VudGl0eS5uYW1lcy5tb2R1bGV9QmFzZVNjaGVtYWA7XG4gICAgY29uc3QgcHJvcE5vZGU6IEVudGl0eVByb3BOb2RlID0ge1xuICAgICAgbm9kZVR5cGU6IFwib2JqZWN0XCIsXG4gICAgICBjaGlsZHJlbjogZW50aXR5LnByb3BzLm1hcCgocHJvcCkgPT4ge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG5vZGVUeXBlOiBcInBsYWluXCIsXG4gICAgICAgICAgcHJvcCxcbiAgICAgICAgfTtcbiAgICAgIH0pLFxuICAgIH07XG5cbiAgICBjb25zdCBzY2hlbWFCb2R5ID0gKCgpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHByb3BOb2RlVG9ab2RUeXBlRGVmKHByb3BOb2RlLCBpbXBvcnRLZXlzKTtcbiAgICAgIGlmIChyZXN1bHQuZW5kc1dpdGgoXCIsXCIpKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQuc2xpY2UoMCwgLTEpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pKCk7XG5cbiAgICAvLyBmdWxsdGV4dCBpbmRleOyXkCDtj6ztlajrkJwg7Lus65+865OkIOy2lOy2nFxuICAgIC8vIFRPRE86IEdJTi9HaVNUIOyduOuNseyKpCDsg53shLHrkJwg7Lus65+8IOy2lOy2nFxuICAgIGNvbnN0IGZ1bGx0ZXh0Q29sdW1uczogRW50aXR5SW5kZXhbXCJjb2x1bW5zXCJdW10gPSBbXTtcblxuICAgIC8vIHZpcnR1YWwgcHJvcHMgKHZpcnR1YWxUeXBlOiBcImNvZGVcIiDrmJDripQgdW5kZWZpbmVk7J24IOqyg+unjCDtj6ztlagpXG4gICAgY29uc3QgdmlydHVhbFByb3BzID0gZW50aXR5LnByb3BzXG4gICAgICAuZmlsdGVyKChwcm9wKSA9PiBpc1ZpcnR1YWxDb2RlUHJvcChwcm9wKSlcbiAgICAgIC5tYXAoKHByb3ApID0+IHByb3AubmFtZSk7XG5cbiAgICAvLyBxdWVyeSB2aXJ0dWFsIHByb3BzICh2aXJ0dWFsVHlwZTogXCJxdWVyeVwi7J24IOqyg+unjCDtj6ztlagpXG4gICAgY29uc3QgdmlydHVhbFF1ZXJ5UHJvcHMgPSBlbnRpdHkucHJvcHNcbiAgICAgIC5maWx0ZXIoKHByb3ApID0+IGlzVmlydHVhbFF1ZXJ5UHJvcChwcm9wKSlcbiAgICAgIC5tYXAoKHByb3ApID0+IHByb3AubmFtZSk7XG5cbiAgICAvKipcbiAgICAgKiBoYXNEZWZhdWx0IHByb3BzXG4gICAgICogLSBudWxsYWJsZSDrmJDripQgZGJEZWZhdWx06rCAIOyeiOuKlCDsu6zrn7wgKGlkIO2PrO2VqClcbiAgICAgKiAtIHJlbGF0aW9u7J20IOyVhOuLiOqxsOuCmCwgcmVsYXRpb27snbTslrTrj4QgbnVsbGFibGXsnbTrqbQg7Y+s7ZWoXG4gICAgICovXG4gICAgY29uc3QgaGFzRGVmYXVsdENvbHVtbnMgPSBlbnRpdHkucHJvcHNcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChwcm9wKSA9PlxuICAgICAgICAgIChwcm9wLnR5cGUgIT09IFwicmVsYXRpb25cIiB8fCBwcm9wLm51bGxhYmxlID09PSB0cnVlKSAmJlxuICAgICAgICAgIChwcm9wLm51bGxhYmxlID09PSB0cnVlIHx8IChwcm9wLnR5cGUgIT09IFwicmVsYXRpb25cIiAmJiBwcm9wLmRiRGVmYXVsdCAhPT0gdW5kZWZpbmVkKSksXG4gICAgICApXG4gICAgICAubWFwKChwcm9wKSA9PiAocHJvcC50eXBlID09PSBcInJlbGF0aW9uXCIgPyBgJHtwcm9wLm5hbWV9X2lkYCA6IHByb3AubmFtZSkpXG4gICAgICAuY29uY2F0KFwiaWRcIik7XG5cbiAgICAvKipcbiAgICAgKiBoYXNWZWN0b3IgcHJvcHNcbiAgICAgKiAtIHZlY3RvciDtg4DsnoXsnbgg7Lus65+8XG4gICAgICovXG4gICAgY29uc3QgaGFzVmVjdG9yQ29sdW1ucyA9IGVudGl0eS5wcm9wc1xuICAgICAgLmZpbHRlcigocHJvcCkgPT4gcHJvcC50eXBlID09PSBcInZlY3RvclwiIHx8IHByb3AudHlwZSA9PT0gXCJ2ZWN0b3JbXVwiKVxuICAgICAgLm1hcCgocHJvcCkgPT4gcHJvcC5uYW1lKTtcblxuICAgIC8qKlxuICAgICAqIGdlbmVyYXRlZCBwcm9wc1xuICAgICAqIC0gZ2VuZXJhdGVkIOyGjeyEseydtCDsnojripQg7Lus65+8IChJTlNFUlQvVVBEQVRFIOyLnCDqsJIg7KCc6rO1IOu2iOqwgClcbiAgICAgKi9cbiAgICBjb25zdCBnZW5lcmF0ZWRDb2x1bW5zID0gZW50aXR5LnByb3BzXG4gICAgICAuZmlsdGVyKFxuICAgICAgICAocHJvcCkgPT5cbiAgICAgICAgICBwcm9wLnR5cGUgIT09IFwicmVsYXRpb25cIiAmJiAocHJvcC5nZW5lcmF0ZWQgIT09IHVuZGVmaW5lZCB8fCBwcm9wLnR5cGUgPT09IFwic2VhcmNoVGV4dFwiKSxcbiAgICAgIClcbiAgICAgIC5tYXAoKHByb3ApID0+IHByb3AubmFtZSk7XG5cbiAgICBjb25zdCBoYXNNZXRhZGF0YSA9XG4gICAgICBmdWxsdGV4dENvbHVtbnMubGVuZ3RoID4gMCB8fFxuICAgICAgdmlydHVhbFByb3BzLmxlbmd0aCA+IDAgfHxcbiAgICAgIHZpcnR1YWxRdWVyeVByb3BzLmxlbmd0aCA+IDAgfHxcbiAgICAgIGhhc0RlZmF1bHRDb2x1bW5zLmxlbmd0aCA+IDAgfHxcbiAgICAgIGdlbmVyYXRlZENvbHVtbnMubGVuZ3RoID4gMCB8fFxuICAgICAgaGFzVmVjdG9yQ29sdW1ucy5sZW5ndGggPiAwO1xuXG4gICAgY29uc3QgbGluZXMgPSBbXG4gICAgICBgZXhwb3J0IGNvbnN0ICR7c2NoZW1hTmFtZX0gPSAke3NjaGVtYUJvZHl9O2AsXG4gICAgICBgZXhwb3J0IHR5cGUgJHtzY2hlbWFOYW1lfSA9IHouaW5mZXI8dHlwZW9mICR7c2NoZW1hTmFtZX0+YCArXG4gICAgICAgIChoYXNNZXRhZGF0YVxuICAgICAgICAgID8gYCAmIHske1xuICAgICAgICAgICAgICAoZnVsbHRleHRDb2x1bW5zLmxlbmd0aCA+IDBcbiAgICAgICAgICAgICAgICA/IGByZWFkb25seSBfX2Z1bGx0ZXh0X186IHJlYWRvbmx5IFske2Z1bGx0ZXh0Q29sdW1uc1xuICAgICAgICAgICAgICAgICAgICAubWFwKChjb2wpID0+IGBcIiR7Y29sfVwiYClcbiAgICAgICAgICAgICAgICAgICAgLmpvaW4oXCIsIFwiKX1dLGBcbiAgICAgICAgICAgICAgICA6IFwiXCIpICtcbiAgICAgICAgICAgICAgKHZpcnR1YWxQcm9wcy5sZW5ndGggPiAwXG4gICAgICAgICAgICAgICAgPyBgcmVhZG9ubHkgX192aXJ0dWFsX186IHJlYWRvbmx5IFske3ZpcnR1YWxQcm9wcy5tYXAoKHByb3ApID0+IGBcIiR7cHJvcH1cImApLmpvaW4oXCIsIFwiKX1dLGBcbiAgICAgICAgICAgICAgICA6IFwiXCIpICtcbiAgICAgICAgICAgICAgKHZpcnR1YWxRdWVyeVByb3BzLmxlbmd0aCA+IDBcbiAgICAgICAgICAgICAgICA/IGByZWFkb25seSBfX3ZpcnR1YWxfcXVlcnlfXzogcmVhZG9ubHkgWyR7dmlydHVhbFF1ZXJ5UHJvcHMubWFwKChwcm9wKSA9PiBgXCIke3Byb3B9XCJgKS5qb2luKFwiLCBcIil9XSxgXG4gICAgICAgICAgICAgICAgOiBcIlwiKSArXG4gICAgICAgICAgICAgIChoYXNEZWZhdWx0Q29sdW1ucy5sZW5ndGggPiAwXG4gICAgICAgICAgICAgICAgPyBgcmVhZG9ubHkgX19oYXNEZWZhdWx0X186IHJlYWRvbmx5IFske2hhc0RlZmF1bHRDb2x1bW5zXG4gICAgICAgICAgICAgICAgICAgIC5tYXAoKGNvbCkgPT4gYFwiJHtjb2x9XCJgKVxuICAgICAgICAgICAgICAgICAgICAuam9pbihcIiwgXCIpfV0sYFxuICAgICAgICAgICAgICAgIDogXCJcIikgK1xuICAgICAgICAgICAgICAoZ2VuZXJhdGVkQ29sdW1ucy5sZW5ndGggPiAwXG4gICAgICAgICAgICAgICAgPyBgcmVhZG9ubHkgX19nZW5lcmF0ZWRfXzogcmVhZG9ubHkgWyR7Z2VuZXJhdGVkQ29sdW1uc1xuICAgICAgICAgICAgICAgICAgICAubWFwKChjb2wpID0+IGBcIiR7Y29sfVwiYClcbiAgICAgICAgICAgICAgICAgICAgLmpvaW4oXCIsIFwiKX1dLGBcbiAgICAgICAgICAgICAgICA6IFwiXCIpICtcbiAgICAgICAgICAgICAgKGhhc1ZlY3RvckNvbHVtbnMubGVuZ3RoID4gMFxuICAgICAgICAgICAgICAgID8gYHJlYWRvbmx5IF9fdmVjdG9yX186IHJlYWRvbmx5IFske2hhc1ZlY3RvckNvbHVtbnNcbiAgICAgICAgICAgICAgICAgICAgLm1hcCgoY29sKSA9PiBgXCIke2NvbH1cImApXG4gICAgICAgICAgICAgICAgICAgIC5qb2luKFwiLCBcIil9XSxgXG4gICAgICAgICAgICAgICAgOiBcIlwiKVxuICAgICAgICAgICAgfX1gXG4gICAgICAgICAgOiBcIlwiKSArXG4gICAgICAgIFwiO1wiLFxuICAgIF07XG5cbiAgICByZXR1cm4ge1xuICAgICAgbGFiZWw6IGBCYXNlU2NoZW1hOiAke2VudGl0eS5pZH1gLFxuICAgICAgaW1wb3J0S2V5cyxcbiAgICAgIGxpbmVzLFxuICAgIH07XG4gIH1cblxuICBnZXRCYXNlTGlzdFBhcmFtc1NvdXJjZUNvZGUoZW50aXR5OiBFbnRpdHkpOiBTb3VyY2VDb2RlIHwgbnVsbCB7XG4gICAgLy8gUHJvcCDsl4bripQgTUTsnbgg6rK97JqwIOyDneyEsSDsoJzsmbhcbiAgICBpZiAoZW50aXR5LnByb3BzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSBlbHNlIGlmIChlbnRpdHkucGFyZW50SWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3Qgc2NoZW1hTmFtZSA9IGAke2VudGl0eS5uYW1lcy5tb2R1bGV9QmFzZUxpc3RQYXJhbXNgO1xuXG4gICAgY29uc3QgZmlsdGVyUHJvcHMgPSBlbnRpdHkucHJvcHMuZmlsdGVyKChwcm9wKSA9PiBwcm9wLnRvRmlsdGVyID09PSB0cnVlKTtcblxuICAgIGNvbnN0IHByb3BOb2RlczogRW50aXR5UHJvcE5vZGVbXSA9IGZpbHRlclByb3BzLm1hcCgocHJvcCkgPT4ge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbm9kZVR5cGU6IFwicGxhaW5cIiBhcyBjb25zdCxcbiAgICAgICAgcHJvcCxcbiAgICAgICAgY2hpbGRyZW46IFtdLFxuICAgICAgfTtcbiAgICB9KTtcblxuICAgIGNvbnN0IGltcG9ydEtleXM6IHN0cmluZ1tdID0gW107XG4gICAgY29uc3QgZmlsdGVyQm9keSA9IHByb3BOb2Rlc1xuICAgICAgLm1hcCgocHJvcE5vZGUpID0+IHByb3BOb2RlVG9ab2RUeXBlRGVmKHByb3BOb2RlLCBpbXBvcnRLZXlzKSlcbiAgICAgIC5qb2luKFwiXFxuXCIpO1xuXG4gICAgLy8gRmlsdGVyUXVlcnkg7YOA7J6F7J2EIOychO2VnCDsoJzsmbjtlaAgcHJvcHMg7LaU7LacICh2aXJ0dWFs66eMIOygnOyZuClcbiAgICBjb25zdCBleGNsdWRlZFByb3BzID0gZW50aXR5LnByb3BzLmZpbHRlcigocCkgPT4gcC50eXBlID09PSBcInZpcnR1YWxcIikubWFwKChwKSA9PiBwLm5hbWUpO1xuXG4gICAgLy8gbnVtZXJpYyDtg4DsnoXsnbggcHJvcHMg7LaU7LacXG4gICAgY29uc3QgbnVtZXJpY1Byb3BzID0gZW50aXR5LnByb3BzLmZpbHRlcigocCkgPT4gcC50eXBlID09PSBcIm51bWVyaWNcIik7XG5cbiAgICAvLyBBcHBseVNvbmFtdUZpbHRlciDtg4DsnoUg7J247J6QIOyDneyEsVxuICAgIGNvbnN0IGVudGl0eVR5cGUgPSBgJHtlbnRpdHkuaWR9QmFzZVNjaGVtYWA7XG4gICAgY29uc3QgbnVtZXJpY0tleXNVbmlvbiA9XG4gICAgICBudW1lcmljUHJvcHMubGVuZ3RoID4gMCA/IG51bWVyaWNQcm9wcy5tYXAoKHByb3ApID0+IGBcIiR7cHJvcC5uYW1lfVwiYCkuam9pbihcIiB8IFwiKSA6IFwibmV2ZXJcIjtcbiAgICBjb25zdCBvbWl0S2V5c1VuaW9uID1cbiAgICAgIGV4Y2x1ZGVkUHJvcHMubGVuZ3RoID4gMCA/IGV4Y2x1ZGVkUHJvcHMubWFwKChuKSA9PiBgXCIke259XCJgKS5qb2luKFwiIHwgXCIpIDogXCJuZXZlclwiO1xuXG4gICAgLy8gUEsg7YOA7J6F7JeQIOuUsOuluCBpZCBab2Qg7YOA7J6FIOqysOyglVxuICAgIGNvbnN0IHBrVHlwZSA9IGVudGl0eS5nZXRQa1R5cGUoKTtcbiAgICBjb25zdCBpZFpvZFR5cGUgPVxuICAgICAgcGtUeXBlID09PSBcInN0cmluZ1wiIHx8IHBrVHlwZSA9PT0gXCJ1dWlkXCJcbiAgICAgICAgPyBcInpBcnJheWFibGUoei5zdHJpbmcoKSlcIlxuICAgICAgICA6IFwiekFycmF5YWJsZSh6Lm51bWJlcigpLmludCgpLnBvc2l0aXZlKCkpXCI7XG5cbiAgICBjb25zdCBzY2hlbWFCb2R5ID0gYFxuei5vYmplY3Qoe1xuICBudW06IHoubnVtYmVyKCkuaW50KCkubm9ubmVnYXRpdmUoKSxcbiAgcGFnZTogei5udW1iZXIoKS5pbnQoKS5taW4oMSksXG4gIHNlYXJjaDogJHtlbnRpdHkuaWR9U2VhcmNoRmllbGQsXG4gIGtleXdvcmQ6IHouc3RyaW5nKCksXG4gIG9yZGVyQnk6ICR7ZW50aXR5LmlkfU9yZGVyQnksXG4gIHF1ZXJ5TW9kZTogU29uYW11UXVlcnlNb2RlLFxuICBpZDogJHtpZFpvZFR5cGV9LFxuICBzb25hbXVGaWx0ZXI6IHouY3VzdG9tPEFwcGx5U29uYW11RmlsdGVyPCR7ZW50aXR5VHlwZX0sICR7b21pdEtleXNVbmlvbn0sICR7bnVtZXJpY0tleXNVbmlvbn0+PigpLCR7ZmlsdGVyQm9keX1cbn0pLnBhcnRpYWwoKTtcbmAudHJpbSgpO1xuXG4gICAgY29uc3QgbGluZXMgPSBbXG4gICAgICBgZXhwb3J0IGNvbnN0ICR7c2NoZW1hTmFtZX0gPSAke3NjaGVtYUJvZHl9O2AsXG4gICAgICBgZXhwb3J0IHR5cGUgJHtzY2hlbWFOYW1lfSA9IHouaW5mZXI8dHlwZW9mICR7c2NoZW1hTmFtZX0+O2AsXG4gICAgXTtcblxuICAgIHJldHVybiB7XG4gICAgICBsYWJlbDogYEJhc2VMaXN0UGFyYW1zOiAke2VudGl0eS5pZH1gLFxuICAgICAgaW1wb3J0S2V5cyxcbiAgICAgIGxpbmVzLFxuICAgIH07XG4gIH1cblxuICBnZXRTdWJzZXRTb3VyY2VDb2RlKGVudGl0eTogRW50aXR5KTogU291cmNlQ29kZSB8IG51bGwge1xuICAgIGlmIChPYmplY3Qua2V5cyhlbnRpdHkuc3Vic2V0cykubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9IGVsc2UgaWYgKGVudGl0eS5wYXJlbnRJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBzdWJzZXRLZXlzID0gT2JqZWN0LmtleXMoZW50aXR5LnN1YnNldHMpO1xuICAgIGNvbnN0IGltcG9ydEtleXM6IHN0cmluZ1tdID0gW107XG4gICAgY29uc3QgbGluZXM6IHN0cmluZ1tdID0gW1xuICAgICAgLi4uc3Vic2V0S2V5cy5mbGF0TWFwKChzdWJzZXRLZXkpID0+IHtcbiAgICAgICAgLy8g7ISc67iM7IWL7JeQ7IScIEZpZWxkRXhwcltdIOqwgOyguOyYtFxuICAgICAgICBjb25zdCBmaWVsZEV4cHJzID0gZW50aXR5LnN1YnNldHNbc3Vic2V0S2V5XTtcblxuICAgICAgICAvLyBGaWVsZEV4cHJbXeuhnCBFbnRpdHlQcm9wTm9kZVtdIOqwgOyguOyYtFxuICAgICAgICBjb25zdCBwcm9wTm9kZXMgPSBlbnRpdHkuZmllbGRFeHByc1RvUHJvcE5vZGVzKGZpZWxkRXhwcnMpO1xuICAgICAgICBjb25zdCBzY2hlbWFOYW1lID0gYCR7ZW50aXR5Lm5hbWVzLm1vZHVsZX1TdWJzZXQke3N1YnNldEtleX1gO1xuICAgICAgICBjb25zdCBwcm9wTm9kZTogRW50aXR5UHJvcE5vZGUgPSB7XG4gICAgICAgICAgbm9kZVR5cGU6IFwib2JqZWN0XCIsXG4gICAgICAgICAgY2hpbGRyZW46IHByb3BOb2RlcyxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBFbnRpdHlQcm9wTm9kZVtd66GcIFpvZFR5cGVEZWYoc3RyaW5nKeydhCDqsIDsoLjsmLRcbiAgICAgICAgY29uc3QgYm9keSA9IHByb3BOb2RlVG9ab2RUeXBlRGVmKHByb3BOb2RlLCBpbXBvcnRLZXlzKTtcblxuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgIGBleHBvcnQgY29uc3QgJHtzY2hlbWFOYW1lfSA9ICR7Ym9keS5yZXBsYWNlKC8sJC8sIFwiXCIpfTtgLFxuICAgICAgICAgIGBleHBvcnQgdHlwZSAke3NjaGVtYU5hbWV9ID0gei5pbmZlcjx0eXBlb2YgJHtzY2hlbWFOYW1lfT47YCxcbiAgICAgICAgXTtcbiAgICAgIH0pLFxuICAgICAgYGV4cG9ydCB0eXBlICR7ZW50aXR5Lm5hbWVzLm1vZHVsZX1TdWJzZXRNYXBwaW5nID0ge2AsXG4gICAgICAuLi5zdWJzZXRLZXlzLm1hcCgoc3Vic2V0S2V5KSA9PiBgICAke3N1YnNldEtleX06ICR7ZW50aXR5Lm5hbWVzLm1vZHVsZX1TdWJzZXQke3N1YnNldEtleX07YCksXG4gICAgICBcIn07XCIsXG4gICAgICBgZXhwb3J0IGNvbnN0ICR7ZW50aXR5Lm5hbWVzLm1vZHVsZX1TdWJzZXRLZXkgPSB6LmVudW0oWyR7c3Vic2V0S2V5c1xuICAgICAgICAubWFwKChrKSA9PiBgXCIke2t9XCJgKVxuICAgICAgICAuam9pbihcIixcIil9XSk7YCxcbiAgICAgIGBleHBvcnQgdHlwZSAke2VudGl0eS5uYW1lcy5tb2R1bGV9U3Vic2V0S2V5ID0gei5pbmZlcjx0eXBlb2YgJHtlbnRpdHkubmFtZXMubW9kdWxlfVN1YnNldEtleT47YCxcbiAgICAgIFwiXCIsXG4gICAgXTtcblxuICAgIHJldHVybiB7XG4gICAgICBsYWJlbDogYFN1YnNldHM6ICR7ZW50aXR5LmlkfWAsXG4gICAgICBsaW5lcyxcbiAgICAgIGltcG9ydEtleXM6IHVuaXF1ZShpbXBvcnRLZXlzKSxcbiAgICB9O1xuICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O1NBSWtDO29CQUV5QjtXQUNsQjtXQUNnQztXQUUxQjtjQUNUO21CQUNtRDtBQU96RixJQUFhLHNCQUFiLGNBQXlDLFNBQVM7Q0FDaEQsY0FBYztFQUNaLE1BQU0sV0FBVztDQUNuQjtDQUVBLG1CQUFtQjtFQUNqQixNQUFNLEVBQUUsUUFBUSxPQUFPLE9BQU87RUFDOUIsT0FBTztHQUNMLFFBQVEsR0FBRyxJQUFJO0dBQ2YsTUFBTTtFQUNSO0NBQ0Y7Q0FDQSxTQUFTO0VBRVAsTUFBTSxXQURZLGNBQWMsVUFDZixDQUFBLENBQVUsS0FBSyxPQUFPLGNBQWMsSUFBSSxFQUFFLENBQUM7RUFHNUQsTUFBTSxjQUFjLFNBQVMsU0FBUyxXQUFXO0dBQy9DLE9BQU87SUFDTCxLQUFLLG1CQUFtQixNQUFNO0lBQzlCLEtBQUssd0JBQXdCLE1BQU07SUFDbkMsS0FBSyw0QkFBNEIsTUFBTTtJQUN2QyxLQUFLLG9CQUFvQixNQUFNO0dBQ2pDLENBQUMsQ0FBQyxPQUFPLFdBQVc7RUFDdEIsQ0FBQztFQUNELE1BQU0sRUFBRSxtQ0FBbUMsV0FBVztFQUd0RCxNQUFNLGtCQUFrQjtHQUFDO0dBQVM7R0FBYztHQUFrQjtHQUFXO0VBQWU7RUFDNUYsWUFBWSxNQUFNLEdBQUcsTUFBTTtHQUN6QixNQUFNLENBQUMsUUFBUSxFQUFF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
|
|
247
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGVkLnRlbXBsYXRlLmpzIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZW1wbGF0ZS9pbXBsZW1lbnRhdGlvbnMvZ2VuZXJhdGVkLnRlbXBsYXRlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuXG5pbXBvcnQgeyB1bmlxdWUgfSBmcm9tIFwicmFkYXNoaVwiO1xuXG5pbXBvcnQgeyBTb25hbXUgfSBmcm9tIFwiLi4vLi4vYXBpXCI7XG5pbXBvcnQgeyB0eXBlIEVudGl0eSB9IGZyb20gXCIuLi8uLi9lbnRpdHkvZW50aXR5XCI7XG5pbXBvcnQgeyBFbnRpdHlNYW5hZ2VyIH0gZnJvbSBcIi4uLy4uL2VudGl0eS9lbnRpdHktbWFuYWdlclwiO1xuaW1wb3J0IHsgTmFpdGUgfSBmcm9tIFwiLi4vLi4vbmFpdGUvbmFpdGVcIjtcbmltcG9ydCB7IGlzVmlydHVhbENvZGVQcm9wLCBpc1ZpcnR1YWxRdWVyeVByb3AgfSBmcm9tIFwiLi4vLi4vdHlwZXMvdHlwZXNcIjtcbmltcG9ydCB7IHR5cGUgRW50aXR5SW5kZXgsIHR5cGUgRW50aXR5UHJvcE5vZGUgfSBmcm9tIFwiLi4vLi4vdHlwZXMvdHlwZXNcIjtcbmltcG9ydCB7IG5vbk51bGxhYmxlIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3V0aWxzXCI7XG5pbXBvcnQgeyBUZW1wbGF0ZSB9IGZyb20gXCIuLi90ZW1wbGF0ZVwiO1xuaW1wb3J0IHsgQlVJTFRfSU5fVFlQRVMsIHByb3BOb2RlVG9ab2RUeXBlRGVmLCB6b2RUeXBlVG9ab2RDb2RlIH0gZnJvbSBcIi4uL3pvZC1jb252ZXJ0ZXJcIjtcblxuZXhwb3J0IHR5cGUgU291cmNlQ29kZSA9IHtcbiAgbGFiZWw6IHN0cmluZztcbiAgbGluZXM6IHN0cmluZ1tdO1xuICBpbXBvcnRLZXlzOiBzdHJpbmdbXTtcbn07XG5leHBvcnQgY2xhc3MgVGVtcGxhdGVfX2dlbmVyYXRlZCBleHRlbmRzIFRlbXBsYXRlIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoXCJnZW5lcmF0ZWRcIik7XG4gIH1cblxuICBnZXRUYXJnZXRBbmRQYXRoKCkge1xuICAgIGNvbnN0IHsgZGlyIH0gPSBTb25hbXUuY29uZmlnLmFwaTtcbiAgICByZXR1cm4ge1xuICAgICAgdGFyZ2V0OiBgJHtkaXJ9L3NyYy9hcHBsaWNhdGlvbmAsXG4gICAgICBwYXRoOiBgc29uYW11LmdlbmVyYXRlZC50c2AsXG4gICAgfTtcbiAgfVxuICByZW5kZXIoKSB7XG4gICAgY29uc3QgZW50aXR5SWRzID0gRW50aXR5TWFuYWdlci5nZXRBbGxJZHMoKTtcbiAgICBjb25zdCBlbnRpdGllcyA9IGVudGl0eUlkcy5tYXAoKGlkKSA9PiBFbnRpdHlNYW5hZ2VyLmdldChpZCkpO1xuXG4gICAgLy8g7KCE7LK0IFNvdXJjZUNvZGUg7IOd7ISxXG4gICAgY29uc3Qgc291cmNlQ29kZXMgPSBlbnRpdGllcy5mbGF0TWFwKChlbnRpdHkpID0+IHtcbiAgICAgIHJldHVybiBbXG4gICAgICAgIHRoaXMuZ2V0RW51bXNTb3VyY2VDb2RlKGVudGl0eSksXG4gICAgICAgIHRoaXMuZ2V0QmFzZVNjaGVtYVNvdXJjZUNvZGUoZW50aXR5KSxcbiAgICAgICAgdGhpcy5nZXRCYXNlTGlzdFBhcmFtc1NvdXJjZUNvZGUoZW50aXR5KSxcbiAgICAgICAgdGhpcy5nZXRTdWJzZXRTb3VyY2VDb2RlKGVudGl0eSksXG4gICAgICBdLmZpbHRlcihub25OdWxsYWJsZSk7XG4gICAgfSk7XG4gICAgTmFpdGUudChcIlRlbXBsYXRlX19nZW5lcmF0ZWQ6c291cmNlQ29kZXNcIiwgc291cmNlQ29kZXMpO1xuXG4gICAgLy8gU29ydFxuICAgIGNvbnN0IExBQkVMX0tFWV9PUkRFUiA9IFtcIkVudW1zXCIsIFwiQmFzZVNjaGVtYVwiLCBcIkJhc2VMaXN0UGFyYW1zXCIsIFwiU3Vic2V0c1wiLCBcIlN1YnNldFF1ZXJpZXNcIl07XG4gICAgc291cmNlQ29kZXMuc29ydCgoYSwgYikgPT4ge1xuICAgICAgY29uc3QgW2FLZXldID0gYS5sYWJlbC5zcGxpdChcIjpcIik7XG4gICAgICBjb25zdCBbYktleV0gPSBiLmxhYmVsLnNwbGl0KFwiOlwiKTtcbiAgICAgIGNvbnN0IGFJbmRleCA9IExBQkVMX0tFWV9PUkRFUi5pbmRleE9mKGFLZXkpO1xuICAgICAgY29uc3QgYkluZGV4ID0gTEFCRUxfS0VZX09SREVSLmluZGV4T2YoYktleSk7XG4gICAgICBpZiAoYUluZGV4ID4gYkluZGV4KSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfSBlbHNlIGlmIChhSW5kZXggPCBiSW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBjb25zdCBzb3VyY2VDb2RlID0gc291cmNlQ29kZXMucmVkdWNlKFxuICAgICAgKHJlc3VsdCwgdHMpID0+IHtcbiAgICAgICAgaWYgKHRzID09PSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGxpbmVzOiBbLi4ucmVzdWx0LmxpbmVzLCBgLy8gJHt0cy5sYWJlbH1gLCAuLi50cy5saW5lcywgXCJcIl0sXG4gICAgICAgICAgaW1wb3J0S2V5czogdW5pcXVlKFsuLi5yZXN1bHQuaW1wb3J0S2V5cywgLi4udHMuaW1wb3J0S2V5c10udG9Tb3J0ZWQoKSksXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBsaW5lczogW10sXG4gICAgICAgIGltcG9ydEtleXM6IFtdLFxuICAgICAgfSBhcyBPbWl0PFNvdXJjZUNvZGUsIFwibGFiZWxcIj4sXG4gICAgKTtcblxuICAgIC8vIC50eXBlcy50c+ydmCDtg4DsnoXsnYQg7LC47KGw7ZWY64qUIOqyveyasCDsiJztmZjssLjsobAo7IOB7Zi47LC47KGwKeqwgCDrsJzsg53tlZjrr4DroZwg7YOA7J6F7J2EIOqwgOyguOyZgCDsnbjrnbzsnbgg7LKY66asXG4gICAgY29uc3QgYWxsVHlwZUtleXMgPSBlbnRpdGllcy5mbGF0TWFwKChlbnRpdHkpID0+IE9iamVjdC5rZXlzKGVudGl0eS50eXBlcykpO1xuICAgIGNvbnN0IGNkSW1wb3J0S2V5cyA9IHNvdXJjZUNvZGUuaW1wb3J0S2V5cy5maWx0ZXIoKGltcG9ydEtleSkgPT5cbiAgICAgIGFsbFR5cGVLZXlzLmluY2x1ZGVzKGltcG9ydEtleSksXG4gICAgKTtcbiAgICBpZiAoY2RJbXBvcnRLZXlzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IGN1c3RvbVNjYWxhckxpbmVzID0gY2RJbXBvcnRLZXlzLmZsYXRNYXAoKGltcG9ydEtleSkgPT4ge1xuICAgICAgICBjb25zdCBlbnRpdHkgPSBlbnRpdGllcy5maW5kKChlbnRpdHkpID0+IGVudGl0eS50eXBlc1tpbXBvcnRLZXldKTtcbiAgICAgICAgaWYgKCFlbnRpdHkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFpvZFR5cGUgbm90IGZvdW5kICR7aW1wb3J0S2V5fWApO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHpvZFR5cGUgPSBlbnRpdHkudHlwZXNbaW1wb3J0S2V5XTtcbiAgICAgICAgYXNzZXJ0KHpvZFR5cGUpO1xuXG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgYC8vIEN1c3RvbVNjYWxhcjogJHtpbXBvcnRLZXl9YCxcbiAgICAgICAgICBgY29uc3QgJHtpbXBvcnRLZXl9ID0gJHt6b2RUeXBlVG9ab2RDb2RlKHpvZFR5cGUsIHNvdXJjZUNvZGUuaW1wb3J0S2V5cyl9O2AsXG4gICAgICAgICAgYHR5cGUgJHtpbXBvcnRLZXl9ID0gei5pbmZlcjx0eXBlb2YgJHtpbXBvcnRLZXl9PmAsXG4gICAgICAgICAgXCJcIixcbiAgICAgICAgXTtcbiAgICAgIH0pO1xuICAgICAgc291cmNlQ29kZS5saW5lcyA9IFsuLi5jdXN0b21TY2FsYXJMaW5lcywgLi4uc291cmNlQ29kZS5saW5lc107XG4gICAgICBzb3VyY2VDb2RlLmltcG9ydEtleXMgPSB1bmlxdWUoXG4gICAgICAgIHNvdXJjZUNvZGUuaW1wb3J0S2V5cy5maWx0ZXIoKGltcG9ydEtleSkgPT4gIWNkSW1wb3J0S2V5cy5pbmNsdWRlcyhpbXBvcnRLZXkpKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgYm9keSA9IHNvdXJjZUNvZGUubGluZXMuam9pbihcIlxcblwiKTtcbiAgICBOYWl0ZS50KFwiVGVtcGxhdGVfX2dlbmVyYXRlZDpib2R5XCIsIGJvZHkpO1xuXG4gICAgLy8gaW1wb3J0XG4gICAgLy8gc291cmNlQ29kZS5pbXBvcnRLZXlz7JeQIOuCtOyepSDtg4DsnoXsnZgg7Iqk7YKk66eI6rCAIOyeiOycvOuptCBzb25hbXUgaW1wb3J07JeQIOy2lOqwgFxuICAgIGNvbnN0IGJ1aWx0SW5TY2hlbWFOYW1lcyA9IE9iamVjdC52YWx1ZXMoQlVJTFRfSU5fVFlQRVMpLm1hcChcbiAgICAgIChpbmZvKSA9PiBpbmZvLnNjaGVtYU5hbWUgYXMgc3RyaW5nLFxuICAgICk7XG4gICAgY29uc3QgYnVpbHRJblNjaGVtYXMgPSBzb3VyY2VDb2RlLmltcG9ydEtleXMuZmlsdGVyKChrZXkpID0+IGJ1aWx0SW5TY2hlbWFOYW1lcy5pbmNsdWRlcyhrZXkpKTtcbiAgICBjb25zdCBzb25hbXVJbXBvcnRzID0gW1xuICAgICAgXCJ6QXJyYXlhYmxlXCIsXG4gICAgICBcIlNRTERhdGVUaW1lU3RyaW5nXCIsXG4gICAgICBcIlN1YnNldFF1ZXJ5XCIsXG4gICAgICBcIlNvbmFtdVF1ZXJ5TW9kZVwiLFxuICAgICAgXCJBcHBseVNvbmFtdUZpbHRlclwiLFxuICAgICAgLi4uYnVpbHRJblNjaGVtYXMsXG4gICAgXS5maWx0ZXIoKG1vZCkgPT4gYm9keS5pbmNsdWRlcyhtb2QpKTtcblxuICAgIHJldHVybiB7XG4gICAgICAuLi50aGlzLmdldFRhcmdldEFuZFBhdGgoKSxcbiAgICAgIGJvZHksXG4gICAgICBpbXBvcnRLZXlzOiBzb3VyY2VDb2RlLmltcG9ydEtleXMsXG4gICAgICBjdXN0b21IZWFkZXJzOiBbXG4gICAgICAgIFwiLyoqXCIsXG4gICAgICAgIFwiICogQGdlbmVyYXRlZFwiLFxuICAgICAgICBcIiAqIOyngeygkSDsiJjsoJXtlZjsp4Ag66eI7IS47JqULlwiLFxuICAgICAgICBcIiAqL1wiLFxuICAgICAgICBcIlwiLFxuICAgICAgICBcIi8qIG94bGludC1kaXNhYmxlICovXCIsXG4gICAgICAgIFwiXCIsXG4gICAgICAgIGBpbXBvcnQgeyB6IH0gZnJvbSAnem9kJztgLFxuICAgICAgICBgaW1wb3J0IHsgJHtzb25hbXVJbXBvcnRzLmpvaW4oXCIsXCIpfSB9IGZyb20gXCJzb25hbXVcIjtgLFxuICAgICAgXSxcbiAgICB9O1xuICB9XG5cbiAgZ2V0RW51bXNTb3VyY2VDb2RlKGVudGl0eTogRW50aXR5KTogU291cmNlQ29kZSB8IG51bGwge1xuICAgIGlmIChPYmplY3Qua2V5cyhlbnRpdHkuZW51bUxhYmVscykubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGxhYmVsOiBgRW51bXM6ICR7ZW50aXR5LmlkfWAsXG4gICAgICBsaW5lczogT2JqZWN0LmVudHJpZXMoZW50aXR5LmVudW1MYWJlbHMpXG4gICAgICAgIC5maWx0ZXIoKFtfLCBlbnVtTGFiZWxdKSA9PiBPYmplY3Qua2V5cyhlbnVtTGFiZWwpLmxlbmd0aCA+IDApXG4gICAgICAgIC5mbGF0TWFwKChbZW51bUlkLCBlbnVtTGFiZWxdKSA9PiBbXG4gICAgICAgICAgYGV4cG9ydCBjb25zdCAke2VudW1JZH0gPSB6LmVudW0oWyR7T2JqZWN0LmtleXMoZW51bUxhYmVsKS5tYXAoXG4gICAgICAgICAgICAoZWwpID0+IGBcIiR7ZWx9XCJgLFxuICAgICAgICAgICl9XSkuZGVzY3JpYmUoXCIke2VudW1JZH1cIik7YCxcbiAgICAgICAgICBgZXhwb3J0IHR5cGUgJHtlbnVtSWR9ID0gei5pbmZlcjx0eXBlb2YgJHtlbnVtSWR9PjtgLFxuICAgICAgICAgIGBleHBvcnQgY29uc3QgJHtlbnVtSWR9TGFiZWwgPSAke0pTT04uc3RyaW5naWZ5KGVudW1MYWJlbCl9O2AsXG4gICAgICAgIF0pLFxuICAgICAgaW1wb3J0S2V5czogW10sXG4gICAgfTtcbiAgfVxuXG4gIGdldEJhc2VTY2hlbWFTb3VyY2VDb2RlKGVudGl0eTogRW50aXR5LCBpbXBvcnRLZXlzOiBzdHJpbmdbXSA9IFtdKTogU291cmNlQ29kZSB7XG4gICAgY29uc3Qgc2NoZW1hTmFtZSA9IGAke2VudGl0eS5uYW1lcy5tb2R1bGV9QmFzZVNjaGVtYWA7XG4gICAgY29uc3QgcHJvcE5vZGU6IEVudGl0eVByb3BOb2RlID0ge1xuICAgICAgbm9kZVR5cGU6IFwib2JqZWN0XCIsXG4gICAgICBjaGlsZHJlbjogZW50aXR5LnByb3BzLm1hcCgocHJvcCkgPT4ge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG5vZGVUeXBlOiBcInBsYWluXCIsXG4gICAgICAgICAgcHJvcCxcbiAgICAgICAgfTtcbiAgICAgIH0pLFxuICAgIH07XG5cbiAgICBjb25zdCBzY2hlbWFCb2R5ID0gKCgpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHByb3BOb2RlVG9ab2RUeXBlRGVmKHByb3BOb2RlLCBpbXBvcnRLZXlzKTtcbiAgICAgIGlmIChyZXN1bHQuZW5kc1dpdGgoXCIsXCIpKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQuc2xpY2UoMCwgLTEpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pKCk7XG5cbiAgICAvLyBmdWxsdGV4dCBpbmRleOyXkCDtj6ztlajrkJwg7Lus65+865OkIOy2lOy2nFxuICAgIC8vIFRPRE86IEdJTi9HaVNUIOyduOuNseyKpCDsg53shLHrkJwg7Lus65+8IOy2lOy2nFxuICAgIGNvbnN0IGZ1bGx0ZXh0Q29sdW1uczogRW50aXR5SW5kZXhbXCJjb2x1bW5zXCJdW10gPSBbXTtcblxuICAgIC8vIHZpcnR1YWwgcHJvcHMgKHZpcnR1YWxUeXBlOiBcImNvZGVcIiDrmJDripQgdW5kZWZpbmVk7J24IOqyg+unjCDtj6ztlagpXG4gICAgY29uc3QgdmlydHVhbFByb3BzID0gZW50aXR5LnByb3BzXG4gICAgICAuZmlsdGVyKChwcm9wKSA9PiBpc1ZpcnR1YWxDb2RlUHJvcChwcm9wKSlcbiAgICAgIC5tYXAoKHByb3ApID0+IHByb3AubmFtZSk7XG5cbiAgICAvLyBxdWVyeSB2aXJ0dWFsIHByb3BzICh2aXJ0dWFsVHlwZTogXCJxdWVyeVwi7J24IOqyg+unjCDtj6ztlagpXG4gICAgY29uc3QgdmlydHVhbFF1ZXJ5UHJvcHMgPSBlbnRpdHkucHJvcHNcbiAgICAgIC5maWx0ZXIoKHByb3ApID0+IGlzVmlydHVhbFF1ZXJ5UHJvcChwcm9wKSlcbiAgICAgIC5tYXAoKHByb3ApID0+IHByb3AubmFtZSk7XG5cbiAgICAvKipcbiAgICAgKiBoYXNEZWZhdWx0IHByb3BzXG4gICAgICogLSBudWxsYWJsZSDrmJDripQgZGJEZWZhdWx06rCAIOyeiOuKlCDsu6zrn7wgKGlkIO2PrO2VqClcbiAgICAgKiAtIHJlbGF0aW9u7J20IOyVhOuLiOqxsOuCmCwgcmVsYXRpb27snbTslrTrj4QgbnVsbGFibGXsnbTrqbQg7Y+s7ZWoXG4gICAgICovXG4gICAgY29uc3QgaGFzRGVmYXVsdENvbHVtbnMgPSBlbnRpdHkucHJvcHNcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChwcm9wKSA9PlxuICAgICAgICAgIChwcm9wLnR5cGUgIT09IFwicmVsYXRpb25cIiB8fCBwcm9wLm51bGxhYmxlID09PSB0cnVlKSAmJlxuICAgICAgICAgIChwcm9wLm51bGxhYmxlID09PSB0cnVlIHx8IChwcm9wLnR5cGUgIT09IFwicmVsYXRpb25cIiAmJiBwcm9wLmRiRGVmYXVsdCAhPT0gdW5kZWZpbmVkKSksXG4gICAgICApXG4gICAgICAubWFwKChwcm9wKSA9PiAocHJvcC50eXBlID09PSBcInJlbGF0aW9uXCIgPyBgJHtwcm9wLm5hbWV9X2lkYCA6IHByb3AubmFtZSkpXG4gICAgICAuY29uY2F0KFwiaWRcIik7XG5cbiAgICAvKipcbiAgICAgKiBoYXNWZWN0b3IgcHJvcHNcbiAgICAgKiAtIHZlY3RvciDtg4DsnoXsnbgg7Lus65+8XG4gICAgICovXG4gICAgY29uc3QgaGFzVmVjdG9yQ29sdW1ucyA9IGVudGl0eS5wcm9wc1xuICAgICAgLmZpbHRlcigocHJvcCkgPT4gcHJvcC50eXBlID09PSBcInZlY3RvclwiIHx8IHByb3AudHlwZSA9PT0gXCJ2ZWN0b3JbXVwiKVxuICAgICAgLm1hcCgocHJvcCkgPT4gcHJvcC5uYW1lKTtcblxuICAgIC8qKlxuICAgICAqIEpTT04gcHJvcHNcbiAgICAgKiAtIGpzb24g7YOA7J6F7J24IOy7rOufvFxuICAgICAqL1xuICAgIGNvbnN0IGpzb25Db2x1bW5zID0gZW50aXR5LnByb3BzXG4gICAgICAuZmlsdGVyKChwcm9wKSA9PiBwcm9wLnR5cGUgPT09IFwianNvblwiKVxuICAgICAgLm1hcCgocHJvcCkgPT4gcHJvcC5uYW1lKTtcblxuICAgIC8qKlxuICAgICAqIGdlbmVyYXRlZCBwcm9wc1xuICAgICAqIC0gZ2VuZXJhdGVkIOyGjeyEseydtCDsnojripQg7Lus65+8IChJTlNFUlQvVVBEQVRFIOyLnCDqsJIg7KCc6rO1IOu2iOqwgClcbiAgICAgKi9cbiAgICBjb25zdCBnZW5lcmF0ZWRDb2x1bW5zID0gZW50aXR5LnByb3BzXG4gICAgICAuZmlsdGVyKFxuICAgICAgICAocHJvcCkgPT5cbiAgICAgICAgICBwcm9wLnR5cGUgIT09IFwicmVsYXRpb25cIiAmJiAocHJvcC5nZW5lcmF0ZWQgIT09IHVuZGVmaW5lZCB8fCBwcm9wLnR5cGUgPT09IFwic2VhcmNoVGV4dFwiKSxcbiAgICAgIClcbiAgICAgIC5tYXAoKHByb3ApID0+IHByb3AubmFtZSk7XG5cbiAgICBjb25zdCBoYXNNZXRhZGF0YSA9XG4gICAgICBmdWxsdGV4dENvbHVtbnMubGVuZ3RoID4gMCB8fFxuICAgICAgdmlydHVhbFByb3BzLmxlbmd0aCA+IDAgfHxcbiAgICAgIHZpcnR1YWxRdWVyeVByb3BzLmxlbmd0aCA+IDAgfHxcbiAgICAgIGhhc0RlZmF1bHRDb2x1bW5zLmxlbmd0aCA+IDAgfHxcbiAgICAgIGdlbmVyYXRlZENvbHVtbnMubGVuZ3RoID4gMCB8fFxuICAgICAgaGFzVmVjdG9yQ29sdW1ucy5sZW5ndGggPiAwIHx8XG4gICAgICBqc29uQ29sdW1ucy5sZW5ndGggPiAwO1xuXG4gICAgY29uc3QgbGluZXMgPSBbXG4gICAgICBgZXhwb3J0IGNvbnN0ICR7c2NoZW1hTmFtZX0gPSAke3NjaGVtYUJvZHl9O2AsXG4gICAgICBgZXhwb3J0IHR5cGUgJHtzY2hlbWFOYW1lfSA9IHouaW5mZXI8dHlwZW9mICR7c2NoZW1hTmFtZX0+YCArXG4gICAgICAgIChoYXNNZXRhZGF0YVxuICAgICAgICAgID8gYCAmIHske1xuICAgICAgICAgICAgICAoZnVsbHRleHRDb2x1bW5zLmxlbmd0aCA+IDBcbiAgICAgICAgICAgICAgICA/IGByZWFkb25seSBfX2Z1bGx0ZXh0X186IHJlYWRvbmx5IFske2Z1bGx0ZXh0Q29sdW1uc1xuICAgICAgICAgICAgICAgICAgICAubWFwKChjb2wpID0+IGBcIiR7Y29sfVwiYClcbiAgICAgICAgICAgICAgICAgICAgLmpvaW4oXCIsIFwiKX1dLGBcbiAgICAgICAgICAgICAgICA6IFwiXCIpICtcbiAgICAgICAgICAgICAgKHZpcnR1YWxQcm9wcy5sZW5ndGggPiAwXG4gICAgICAgICAgICAgICAgPyBgcmVhZG9ubHkgX192aXJ0dWFsX186IHJlYWRvbmx5IFske3ZpcnR1YWxQcm9wcy5tYXAoKHByb3ApID0+IGBcIiR7cHJvcH1cImApLmpvaW4oXCIsIFwiKX1dLGBcbiAgICAgICAgICAgICAgICA6IFwiXCIpICtcbiAgICAgICAgICAgICAgKHZpcnR1YWxRdWVyeVByb3BzLmxlbmd0aCA+IDBcbiAgICAgICAgICAgICAgICA/IGByZWFkb25seSBfX3ZpcnR1YWxfcXVlcnlfXzogcmVhZG9ubHkgWyR7dmlydHVhbFF1ZXJ5UHJvcHMubWFwKChwcm9wKSA9PiBgXCIke3Byb3B9XCJgKS5qb2luKFwiLCBcIil9XSxgXG4gICAgICAgICAgICAgICAgOiBcIlwiKSArXG4gICAgICAgICAgICAgIChoYXNEZWZhdWx0Q29sdW1ucy5sZW5ndGggPiAwXG4gICAgICAgICAgICAgICAgPyBgcmVhZG9ubHkgX19oYXNEZWZhdWx0X186IHJlYWRvbmx5IFske2hhc0RlZmF1bHRDb2x1bW5zXG4gICAgICAgICAgICAgICAgICAgIC5tYXAoKGNvbCkgPT4gYFwiJHtjb2x9XCJgKVxuICAgICAgICAgICAgICAgICAgICAuam9pbihcIiwgXCIpfV0sYFxuICAgICAgICAgICAgICAgIDogXCJcIikgK1xuICAgICAgICAgICAgICAoZ2VuZXJhdGVkQ29sdW1ucy5sZW5ndGggPiAwXG4gICAgICAgICAgICAgICAgPyBgcmVhZG9ubHkgX19nZW5lcmF0ZWRfXzogcmVhZG9ubHkgWyR7Z2VuZXJhdGVkQ29sdW1uc1xuICAgICAgICAgICAgICAgICAgICAubWFwKChjb2wpID0+IGBcIiR7Y29sfVwiYClcbiAgICAgICAgICAgICAgICAgICAgLmpvaW4oXCIsIFwiKX1dLGBcbiAgICAgICAgICAgICAgICA6IFwiXCIpICtcbiAgICAgICAgICAgICAgKGhhc1ZlY3RvckNvbHVtbnMubGVuZ3RoID4gMFxuICAgICAgICAgICAgICAgID8gYHJlYWRvbmx5IF9fdmVjdG9yX186IHJlYWRvbmx5IFske2hhc1ZlY3RvckNvbHVtbnNcbiAgICAgICAgICAgICAgICAgICAgLm1hcCgoY29sKSA9PiBgXCIke2NvbH1cImApXG4gICAgICAgICAgICAgICAgICAgIC5qb2luKFwiLCBcIil9XSxgXG4gICAgICAgICAgICAgICAgOiBcIlwiKSArXG4gICAgICAgICAgICAgIChqc29uQ29sdW1ucy5sZW5ndGggPiAwXG4gICAgICAgICAgICAgICAgPyBgcmVhZG9ubHkgX19qc29uX186IHJlYWRvbmx5IFske2pzb25Db2x1bW5zXG4gICAgICAgICAgICAgICAgICAgIC5tYXAoKGNvbCkgPT4gYFwiJHtjb2x9XCJgKVxuICAgICAgICAgICAgICAgICAgICAuam9pbihcIiwgXCIpfV0sYFxuICAgICAgICAgICAgICAgIDogXCJcIilcbiAgICAgICAgICAgIH19YFxuICAgICAgICAgIDogXCJcIikgK1xuICAgICAgICBcIjtcIixcbiAgICBdO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGxhYmVsOiBgQmFzZVNjaGVtYTogJHtlbnRpdHkuaWR9YCxcbiAgICAgIGltcG9ydEtleXMsXG4gICAgICBsaW5lcyxcbiAgICB9O1xuICB9XG5cbiAgZ2V0QmFzZUxpc3RQYXJhbXNTb3VyY2VDb2RlKGVudGl0eTogRW50aXR5KTogU291cmNlQ29kZSB8IG51bGwge1xuICAgIC8vIFByb3Ag7JeG64qUIE1E7J24IOqyveyasCDsg53shLEg7KCc7Jm4XG4gICAgaWYgKGVudGl0eS5wcm9wcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0gZWxzZSBpZiAoZW50aXR5LnBhcmVudElkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IHNjaGVtYU5hbWUgPSBgJHtlbnRpdHkubmFtZXMubW9kdWxlfUJhc2VMaXN0UGFyYW1zYDtcblxuICAgIGNvbnN0IGZpbHRlclByb3BzID0gZW50aXR5LnByb3BzLmZpbHRlcigocHJvcCkgPT4gcHJvcC50b0ZpbHRlciA9PT0gdHJ1ZSk7XG5cbiAgICBjb25zdCBwcm9wTm9kZXM6IEVudGl0eVByb3BOb2RlW10gPSBmaWx0ZXJQcm9wcy5tYXAoKHByb3ApID0+IHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG5vZGVUeXBlOiBcInBsYWluXCIgYXMgY29uc3QsXG4gICAgICAgIHByb3AsXG4gICAgICAgIGNoaWxkcmVuOiBbXSxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICBjb25zdCBpbXBvcnRLZXlzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGNvbnN0IGZpbHRlckJvZHkgPSBwcm9wTm9kZXNcbiAgICAgIC5tYXAoKHByb3BOb2RlKSA9PiBwcm9wTm9kZVRvWm9kVHlwZURlZihwcm9wTm9kZSwgaW1wb3J0S2V5cykpXG4gICAgICAuam9pbihcIlxcblwiKTtcblxuICAgIC8vIEZpbHRlclF1ZXJ5IO2DgOyeheydhCDsnITtlZwg7KCc7Jm47ZWgIHByb3BzIOy2lOy2nCAodmlydHVhbOunjCDsoJzsmbgpXG4gICAgY29uc3QgZXhjbHVkZWRQcm9wcyA9IGVudGl0eS5wcm9wcy5maWx0ZXIoKHApID0+IHAudHlwZSA9PT0gXCJ2aXJ0dWFsXCIpLm1hcCgocCkgPT4gcC5uYW1lKTtcblxuICAgIC8vIG51bWVyaWMg7YOA7J6F7J24IHByb3BzIOy2lOy2nFxuICAgIGNvbnN0IG51bWVyaWNQcm9wcyA9IGVudGl0eS5wcm9wcy5maWx0ZXIoKHApID0+IHAudHlwZSA9PT0gXCJudW1lcmljXCIpO1xuXG4gICAgLy8gQXBwbHlTb25hbXVGaWx0ZXIg7YOA7J6FIOyduOyekCDsg53shLFcbiAgICBjb25zdCBlbnRpdHlUeXBlID0gYCR7ZW50aXR5LmlkfUJhc2VTY2hlbWFgO1xuICAgIGNvbnN0IG51bWVyaWNLZXlzVW5pb24gPVxuICAgICAgbnVtZXJpY1Byb3BzLmxlbmd0aCA+IDAgPyBudW1lcmljUHJvcHMubWFwKChwcm9wKSA9PiBgXCIke3Byb3AubmFtZX1cImApLmpvaW4oXCIgfCBcIikgOiBcIm5ldmVyXCI7XG4gICAgY29uc3Qgb21pdEtleXNVbmlvbiA9XG4gICAgICBleGNsdWRlZFByb3BzLmxlbmd0aCA+IDAgPyBleGNsdWRlZFByb3BzLm1hcCgobikgPT4gYFwiJHtufVwiYCkuam9pbihcIiB8IFwiKSA6IFwibmV2ZXJcIjtcblxuICAgIC8vIFBLIO2DgOyeheyXkCDrlLDrpbggaWQgWm9kIO2DgOyehSDqsrDsoJVcbiAgICBjb25zdCBwa1R5cGUgPSBlbnRpdHkuZ2V0UGtUeXBlKCk7XG4gICAgY29uc3QgaWRab2RUeXBlID1cbiAgICAgIHBrVHlwZSA9PT0gXCJzdHJpbmdcIiB8fCBwa1R5cGUgPT09IFwidXVpZFwiXG4gICAgICAgID8gXCJ6QXJyYXlhYmxlKHouc3RyaW5nKCkpXCJcbiAgICAgICAgOiBcInpBcnJheWFibGUoei5udW1iZXIoKS5pbnQoKS5wb3NpdGl2ZSgpKVwiO1xuXG4gICAgY29uc3Qgc2NoZW1hQm9keSA9IGBcbnoub2JqZWN0KHtcbiAgbnVtOiB6Lm51bWJlcigpLmludCgpLm5vbm5lZ2F0aXZlKCksXG4gIHBhZ2U6IHoubnVtYmVyKCkuaW50KCkubWluKDEpLFxuICBzZWFyY2g6ICR7ZW50aXR5LmlkfVNlYXJjaEZpZWxkLFxuICBrZXl3b3JkOiB6LnN0cmluZygpLFxuICBvcmRlckJ5OiAke2VudGl0eS5pZH1PcmRlckJ5LFxuICBxdWVyeU1vZGU6IFNvbmFtdVF1ZXJ5TW9kZSxcbiAgaWQ6ICR7aWRab2RUeXBlfSxcbiAgc29uYW11RmlsdGVyOiB6LmN1c3RvbTxBcHBseVNvbmFtdUZpbHRlcjwke2VudGl0eVR5cGV9LCAke29taXRLZXlzVW5pb259LCAke251bWVyaWNLZXlzVW5pb259Pj4oKSwke2ZpbHRlckJvZHl9XG59KS5wYXJ0aWFsKCk7XG5gLnRyaW0oKTtcblxuICAgIGNvbnN0IGxpbmVzID0gW1xuICAgICAgYGV4cG9ydCBjb25zdCAke3NjaGVtYU5hbWV9ID0gJHtzY2hlbWFCb2R5fTtgLFxuICAgICAgYGV4cG9ydCB0eXBlICR7c2NoZW1hTmFtZX0gPSB6LmluZmVyPHR5cGVvZiAke3NjaGVtYU5hbWV9PjtgLFxuICAgIF07XG5cbiAgICByZXR1cm4ge1xuICAgICAgbGFiZWw6IGBCYXNlTGlzdFBhcmFtczogJHtlbnRpdHkuaWR9YCxcbiAgICAgIGltcG9ydEtleXMsXG4gICAgICBsaW5lcyxcbiAgICB9O1xuICB9XG5cbiAgZ2V0U3Vic2V0U291cmNlQ29kZShlbnRpdHk6IEVudGl0eSk6IFNvdXJjZUNvZGUgfCBudWxsIHtcbiAgICBpZiAoT2JqZWN0LmtleXMoZW50aXR5LnN1YnNldHMpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSBlbHNlIGlmIChlbnRpdHkucGFyZW50SWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3Qgc3Vic2V0S2V5cyA9IE9iamVjdC5rZXlzKGVudGl0eS5zdWJzZXRzKTtcbiAgICBjb25zdCBpbXBvcnRLZXlzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGNvbnN0IGxpbmVzOiBzdHJpbmdbXSA9IFtcbiAgICAgIC4uLnN1YnNldEtleXMuZmxhdE1hcCgoc3Vic2V0S2V5KSA9PiB7XG4gICAgICAgIC8vIOyEnOu4jOyFi+yXkOyEnCBGaWVsZEV4cHJbXSDqsIDsoLjsmLRcbiAgICAgICAgY29uc3QgZmllbGRFeHBycyA9IGVudGl0eS5zdWJzZXRzW3N1YnNldEtleV07XG5cbiAgICAgICAgLy8gRmllbGRFeHByW13roZwgRW50aXR5UHJvcE5vZGVbXSDqsIDsoLjsmLRcbiAgICAgICAgY29uc3QgcHJvcE5vZGVzID0gZW50aXR5LmZpZWxkRXhwcnNUb1Byb3BOb2RlcyhmaWVsZEV4cHJzKTtcbiAgICAgICAgY29uc3Qgc2NoZW1hTmFtZSA9IGAke2VudGl0eS5uYW1lcy5tb2R1bGV9U3Vic2V0JHtzdWJzZXRLZXl9YDtcbiAgICAgICAgY29uc3QgcHJvcE5vZGU6IEVudGl0eVByb3BOb2RlID0ge1xuICAgICAgICAgIG5vZGVUeXBlOiBcIm9iamVjdFwiLFxuICAgICAgICAgIGNoaWxkcmVuOiBwcm9wTm9kZXMsXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gRW50aXR5UHJvcE5vZGVbXeuhnCBab2RUeXBlRGVmKHN0cmluZynsnYQg6rCA7KC47Ji0XG4gICAgICAgIGNvbnN0IGJvZHkgPSBwcm9wTm9kZVRvWm9kVHlwZURlZihwcm9wTm9kZSwgaW1wb3J0S2V5cyk7XG5cbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICBgZXhwb3J0IGNvbnN0ICR7c2NoZW1hTmFtZX0gPSAke2JvZHkucmVwbGFjZSgvLCQvLCBcIlwiKX07YCxcbiAgICAgICAgICBgZXhwb3J0IHR5cGUgJHtzY2hlbWFOYW1lfSA9IHouaW5mZXI8dHlwZW9mICR7c2NoZW1hTmFtZX0+O2AsXG4gICAgICAgIF07XG4gICAgICB9KSxcbiAgICAgIGBleHBvcnQgdHlwZSAke2VudGl0eS5uYW1lcy5tb2R1bGV9U3Vic2V0TWFwcGluZyA9IHtgLFxuICAgICAgLi4uc3Vic2V0S2V5cy5tYXAoKHN1YnNldEtleSkgPT4gYCAgJHtzdWJzZXRLZXl9OiAke2VudGl0eS5uYW1lcy5tb2R1bGV9U3Vic2V0JHtzdWJzZXRLZXl9O2ApLFxuICAgICAgXCJ9O1wiLFxuICAgICAgYGV4cG9ydCBjb25zdCAke2VudGl0eS5uYW1lcy5tb2R1bGV9U3Vic2V0S2V5ID0gei5lbnVtKFske3N1YnNldEtleXNcbiAgICAgICAgLm1hcCgoaykgPT4gYFwiJHtrfVwiYClcbiAgICAgICAgLmpvaW4oXCIsXCIpfV0pO2AsXG4gICAgICBgZXhwb3J0IHR5cGUgJHtlbnRpdHkubmFtZXMubW9kdWxlfVN1YnNldEtleSA9IHouaW5mZXI8dHlwZW9mICR7ZW50aXR5Lm5hbWVzLm1vZHVsZX1TdWJzZXRLZXk+O2AsXG4gICAgICBcIlwiLFxuICAgIF07XG5cbiAgICByZXR1cm4ge1xuICAgICAgbGFiZWw6IGBTdWJzZXRzOiAke2VudGl0eS5pZH1gLFxuICAgICAgbGluZXMsXG4gICAgICBpbXBvcnRLZXlzOiB1bmlxdWUoaW1wb3J0S2V5cyksXG4gICAgfTtcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztTQUlrQztvQkFFeUI7V0FDbEI7V0FDZ0M7V0FFMUI7Y0FDVDttQkFDbUQ7QUFPekYsSUFBYSxzQkFBYixjQUF5QyxTQUFTO0NBQ2hELGNBQWM7RUFDWixNQUFNLFdBQVc7Q0FDbkI7Q0FFQSxtQkFBbUI7RUFDakIsTUFBTSxF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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonamu",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.4",
|
|
4
4
|
"description": "Sonamu — TypeScript Fullstack API Framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -130,9 +130,9 @@
|
|
|
130
130
|
"vite": "8.0.16",
|
|
131
131
|
"vitest": "^4.1.9",
|
|
132
132
|
"@sonamu-kit/hmr-hook": "^0.5.1",
|
|
133
|
+
"@sonamu-kit/tasks": "^0.3.1",
|
|
133
134
|
"@sonamu-kit/hmr-runner": "^0.2.0",
|
|
134
|
-
"@sonamu-kit/ts-loader": "^2.2.0"
|
|
135
|
-
"@sonamu-kit/tasks": "^0.3.1"
|
|
135
|
+
"@sonamu-kit/ts-loader": "^2.2.0"
|
|
136
136
|
},
|
|
137
137
|
"devDependencies": {
|
|
138
138
|
"@types/bcrypt": "^6",
|
|
@@ -7,6 +7,16 @@ type TestSchema = {
|
|
|
7
7
|
users: {
|
|
8
8
|
id: number;
|
|
9
9
|
name: string;
|
|
10
|
+
payload: {
|
|
11
|
+
actor: {
|
|
12
|
+
id: string;
|
|
13
|
+
role: string;
|
|
14
|
+
};
|
|
15
|
+
message: string;
|
|
16
|
+
};
|
|
17
|
+
tags: string[];
|
|
18
|
+
state: string;
|
|
19
|
+
readonly __json__: readonly ["payload", "tags", "state"];
|
|
10
20
|
};
|
|
11
21
|
};
|
|
12
22
|
|
|
@@ -33,3 +43,59 @@ describe("Puri locking methods", () => {
|
|
|
33
43
|
expect(query).toBe('select * from "users" where "id" = 1 limit 1 for share');
|
|
34
44
|
});
|
|
35
45
|
});
|
|
46
|
+
|
|
47
|
+
describe("Puri JSONB containment", () => {
|
|
48
|
+
it("object array scalar and hostile-looking values remain serialized bindings", () => {
|
|
49
|
+
const hostileValue = `x' OR 1=1 --`;
|
|
50
|
+
const objectQuery = usersQuery()
|
|
51
|
+
.whereJsonSupersetOf("users.payload", {
|
|
52
|
+
actor: { id: hostileValue },
|
|
53
|
+
})
|
|
54
|
+
.rawQuery()
|
|
55
|
+
.toSQL();
|
|
56
|
+
const arrayQuery = usersQuery().whereJsonSupersetOf("tags", [hostileValue]).rawQuery().toSQL();
|
|
57
|
+
const scalarQuery = usersQuery().whereJsonSupersetOf("state", hostileValue).rawQuery().toSQL();
|
|
58
|
+
|
|
59
|
+
expect(objectQuery.sql).toBe('select * from "users" where "users"."payload" @> ?');
|
|
60
|
+
expect(objectQuery.bindings).toEqual([
|
|
61
|
+
JSON.stringify({
|
|
62
|
+
actor: { id: hostileValue },
|
|
63
|
+
}),
|
|
64
|
+
]);
|
|
65
|
+
expect(arrayQuery.sql).toBe('select * from "users" where "tags" @> ?');
|
|
66
|
+
expect(arrayQuery.bindings).toEqual([JSON.stringify([hostileValue])]);
|
|
67
|
+
expect(scalarQuery.sql).toBe('select * from "users" where "state" @> ?');
|
|
68
|
+
expect(scalarQuery.bindings).toEqual([JSON.stringify(hostileValue)]);
|
|
69
|
+
|
|
70
|
+
expect(objectQuery.sql).not.toContain(hostileValue);
|
|
71
|
+
expect(arrayQuery.sql).not.toContain(hostileValue);
|
|
72
|
+
expect(scalarQuery.sql).not.toContain(hostileValue);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("WhereGroup preserves AND OR ordering and undefined is rejected", () => {
|
|
76
|
+
const groupedQuery = usersQuery()
|
|
77
|
+
.where("id", 1)
|
|
78
|
+
.whereGroup((group) => {
|
|
79
|
+
group
|
|
80
|
+
.whereJsonSupersetOf("payload", { actor: { role: "admin" } })
|
|
81
|
+
.orWhereJsonSupersetOf("tags", ["urgent"]);
|
|
82
|
+
})
|
|
83
|
+
.rawQuery()
|
|
84
|
+
.toSQL();
|
|
85
|
+
|
|
86
|
+
expect(groupedQuery.sql).toBe(
|
|
87
|
+
'select * from "users" where "id" = ? and ("payload" @> ? or "tags" @> ?)',
|
|
88
|
+
);
|
|
89
|
+
expect(groupedQuery.bindings).toEqual([
|
|
90
|
+
1,
|
|
91
|
+
JSON.stringify({ actor: { role: "admin" } }),
|
|
92
|
+
JSON.stringify(["urgent"]),
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
const query = usersQuery();
|
|
96
|
+
expect(() => Reflect.apply(query.whereJsonSupersetOf, query, ["payload", undefined])).toThrow(
|
|
97
|
+
"Puri JSONB containment value must be JSON-serializable; JSON.stringify returned undefined.",
|
|
98
|
+
);
|
|
99
|
+
expect(query.rawQuery().toSQL().sql).toBe('select * from "users"');
|
|
100
|
+
});
|
|
101
|
+
});
|
package/src/database/puri.ts
CHANGED
|
@@ -20,6 +20,8 @@ import {
|
|
|
20
20
|
type FuzzyOperator,
|
|
21
21
|
type InsertData,
|
|
22
22
|
type InsertResult,
|
|
23
|
+
type JsonColumns,
|
|
24
|
+
type JsonSupersetValue,
|
|
23
25
|
type LeftJoinedMarker,
|
|
24
26
|
type LeftJoinMarkerFor,
|
|
25
27
|
type NumericColumns,
|
|
@@ -70,6 +72,18 @@ function normalizeFuzzyOperator(operator?: string): FuzzyOperator {
|
|
|
70
72
|
return fuzzyOperator;
|
|
71
73
|
}
|
|
72
74
|
|
|
75
|
+
function serializeJsonSupersetValue(value: unknown): string {
|
|
76
|
+
const serialized = JSON.stringify(value);
|
|
77
|
+
|
|
78
|
+
if (serialized === undefined) {
|
|
79
|
+
throw new TypeError(
|
|
80
|
+
"Puri JSONB containment value must be JSON-serializable; JSON.stringify returned undefined.",
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return serialized;
|
|
85
|
+
}
|
|
86
|
+
|
|
73
87
|
function normalizeOrderByDirection(direction: PuriOrderByDirection = "asc"): PuriOrderByDirection {
|
|
74
88
|
if (direction !== "asc" && direction !== "desc") {
|
|
75
89
|
throw new Error(`Invalid order direction: ${direction}`);
|
|
@@ -784,6 +798,15 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
|
|
|
784
798
|
return this as any;
|
|
785
799
|
}
|
|
786
800
|
|
|
801
|
+
// WHERE JSONB SUPERSET (@>)
|
|
802
|
+
whereJsonSupersetOf<TColumn extends JsonColumns<TTables>>(
|
|
803
|
+
column: TColumn,
|
|
804
|
+
value: JsonSupersetValue<ExtractColumnType<TTables, TColumn>>,
|
|
805
|
+
): this {
|
|
806
|
+
this.knexQuery.whereJsonSupersetOf(column, serializeJsonSupersetValue(value));
|
|
807
|
+
return this;
|
|
808
|
+
}
|
|
809
|
+
|
|
787
810
|
// WHERE MATCH
|
|
788
811
|
whereMatch<TColumn extends FulltextColumns<TTables>>(column: TColumn, value: string): this {
|
|
789
812
|
this.knexQuery.whereRaw(`MATCH (${String(column)}) AGAINST (?)`, [value]);
|
|
@@ -1449,6 +1472,23 @@ export class WhereGroup<TTables extends Record<string, any>> {
|
|
|
1449
1472
|
return this;
|
|
1450
1473
|
}
|
|
1451
1474
|
|
|
1475
|
+
// WHERE JSONB SUPERSET (@>)
|
|
1476
|
+
whereJsonSupersetOf<TColumn extends JsonColumns<TTables>>(
|
|
1477
|
+
column: TColumn,
|
|
1478
|
+
value: JsonSupersetValue<ExtractColumnType<TTables, TColumn>>,
|
|
1479
|
+
): this {
|
|
1480
|
+
this.builder.whereJsonSupersetOf(column, serializeJsonSupersetValue(value));
|
|
1481
|
+
return this;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
orWhereJsonSupersetOf<TColumn extends JsonColumns<TTables>>(
|
|
1485
|
+
column: TColumn,
|
|
1486
|
+
value: JsonSupersetValue<ExtractColumnType<TTables, TColumn>>,
|
|
1487
|
+
): this {
|
|
1488
|
+
this.builder.orWhereJsonSupersetOf(column, serializeJsonSupersetValue(value));
|
|
1489
|
+
return this;
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1452
1492
|
// WHERE MATCH
|
|
1453
1493
|
whereMatch<TColumn extends FulltextColumns<TTables>>(column: TColumn, value: string): this;
|
|
1454
1494
|
whereMatch(...args: any[]): this {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { describe, expectTypeOf, it } from "vitest";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { Puri } from "./puri";
|
|
4
4
|
import {
|
|
5
5
|
type AvailableColumns,
|
|
6
6
|
type ExtractColumnType,
|
|
7
|
+
type JsonColumns,
|
|
8
|
+
type JsonSupersetValue,
|
|
7
9
|
type LeftJoinedMarker,
|
|
8
10
|
type ParseSelectObject,
|
|
9
11
|
} from "./puri.types";
|
|
@@ -18,6 +20,28 @@ type MockSchema = {
|
|
|
18
20
|
name: string;
|
|
19
21
|
email: string;
|
|
20
22
|
department_id: number | null;
|
|
23
|
+
preferences: {
|
|
24
|
+
theme: "light" | "dark";
|
|
25
|
+
notifications: {
|
|
26
|
+
email: boolean;
|
|
27
|
+
sms: boolean;
|
|
28
|
+
};
|
|
29
|
+
labels: string[];
|
|
30
|
+
sessions: {
|
|
31
|
+
id: string;
|
|
32
|
+
active: boolean;
|
|
33
|
+
}[];
|
|
34
|
+
};
|
|
35
|
+
json_tags: string[];
|
|
36
|
+
json_scalar: string;
|
|
37
|
+
nullable_payload: {
|
|
38
|
+
enabled: boolean;
|
|
39
|
+
} | null;
|
|
40
|
+
native_tags: string[];
|
|
41
|
+
created_at: Date;
|
|
42
|
+
embedding: number[];
|
|
43
|
+
readonly __json__: readonly ["preferences", "json_tags", "json_scalar", "nullable_payload"];
|
|
44
|
+
readonly __vector__: readonly ["embedding"];
|
|
21
45
|
};
|
|
22
46
|
departments: {
|
|
23
47
|
id: number;
|
|
@@ -458,6 +482,96 @@ describe("AvailableColumns", () => {
|
|
|
458
482
|
});
|
|
459
483
|
});
|
|
460
484
|
|
|
485
|
+
describe("JsonColumns and JsonSupersetValue", () => {
|
|
486
|
+
it("JSON metadata selects only JSON columns and preserves recursive RHS types", () => {
|
|
487
|
+
type Tables = { users: MockSchema["users"] };
|
|
488
|
+
type Columns = JsonColumns<Tables>;
|
|
489
|
+
type PreferencesValue = JsonSupersetValue<MockSchema["users"]["preferences"]>;
|
|
490
|
+
type NullablePayloadValue = JsonSupersetValue<MockSchema["users"]["nullable_payload"]>;
|
|
491
|
+
|
|
492
|
+
expectTypeOf<Columns>().toEqualTypeOf<
|
|
493
|
+
| "users.preferences"
|
|
494
|
+
| "users.json_tags"
|
|
495
|
+
| "users.json_scalar"
|
|
496
|
+
| "users.nullable_payload"
|
|
497
|
+
| "preferences"
|
|
498
|
+
| "json_tags"
|
|
499
|
+
| "json_scalar"
|
|
500
|
+
| "nullable_payload"
|
|
501
|
+
>();
|
|
502
|
+
|
|
503
|
+
const partialObject: PreferencesValue = {
|
|
504
|
+
notifications: { email: true },
|
|
505
|
+
sessions: [{ active: false }],
|
|
506
|
+
};
|
|
507
|
+
const arrayRoot: JsonSupersetValue<MockSchema["users"]["json_tags"]> = ["urgent"];
|
|
508
|
+
const scalarRoot: JsonSupersetValue<MockSchema["users"]["json_scalar"]> = "active";
|
|
509
|
+
const nullableColumnValue: NullablePayloadValue = { enabled: true };
|
|
510
|
+
|
|
511
|
+
expectTypeOf(partialObject).toExtend<PreferencesValue>();
|
|
512
|
+
expectTypeOf(arrayRoot).toEqualTypeOf<string[]>();
|
|
513
|
+
expectTypeOf(scalarRoot).toEqualTypeOf<string>();
|
|
514
|
+
expectTypeOf(nullableColumnValue).toExtend<NullablePayloadValue>();
|
|
515
|
+
|
|
516
|
+
// @ts-expect-error nested boolean property must not accept a string.
|
|
517
|
+
const wrongNestedType: PreferencesValue = { notifications: { email: "yes" } };
|
|
518
|
+
// @ts-expect-error array element types are preserved.
|
|
519
|
+
const wrongArrayElement: JsonSupersetValue<MockSchema["users"]["json_tags"]> = [1];
|
|
520
|
+
// @ts-expect-error object array elements retain their recursive partial shape.
|
|
521
|
+
const wrongObjectArrayElement: PreferencesValue = { sessions: [{ active: "yes" }] };
|
|
522
|
+
// @ts-expect-error nullable JSON columns do not accept top-level null as a containment value.
|
|
523
|
+
const nullRoot: NullablePayloadValue = null;
|
|
524
|
+
// @ts-expect-error undefined cannot be serialized as a JSONB containment value.
|
|
525
|
+
const undefinedRoot: PreferencesValue = undefined;
|
|
526
|
+
|
|
527
|
+
const unknownValue: unknown = { notifications: { email: true } };
|
|
528
|
+
// @ts-expect-error unknown must be narrowed before it can be used as a containment value.
|
|
529
|
+
const unknownRoot: PreferencesValue = unknownValue;
|
|
530
|
+
|
|
531
|
+
expectTypeOf(wrongNestedType).toExtend<PreferencesValue>();
|
|
532
|
+
expectTypeOf(wrongArrayElement).toEqualTypeOf<string[]>();
|
|
533
|
+
expectTypeOf(wrongObjectArrayElement).toExtend<PreferencesValue>();
|
|
534
|
+
expectTypeOf(nullRoot).toExtend<NullablePayloadValue>();
|
|
535
|
+
expectTypeOf(undefinedRoot).toExtend<PreferencesValue>();
|
|
536
|
+
expectTypeOf(unknownRoot).toExtend<PreferencesValue>();
|
|
537
|
+
|
|
538
|
+
type Query = Puri<MockSchema, Tables, MockSchema["users"]>;
|
|
539
|
+
const query = {} as Query;
|
|
540
|
+
|
|
541
|
+
expectTypeOf(
|
|
542
|
+
query.whereJsonSupersetOf("preferences", {
|
|
543
|
+
notifications: { sms: false },
|
|
544
|
+
}),
|
|
545
|
+
).toEqualTypeOf<Query>();
|
|
546
|
+
expectTypeOf(
|
|
547
|
+
query.whereGroup((group) =>
|
|
548
|
+
group
|
|
549
|
+
.whereJsonSupersetOf("users.preferences", { theme: "dark" })
|
|
550
|
+
.orWhereJsonSupersetOf("users.json_tags", ["urgent"]),
|
|
551
|
+
),
|
|
552
|
+
).toEqualTypeOf<Query>();
|
|
553
|
+
|
|
554
|
+
// @ts-expect-error ordinary string columns are not JSON columns.
|
|
555
|
+
query.whereJsonSupersetOf("name", "Noa");
|
|
556
|
+
// @ts-expect-error date columns are not JSON columns.
|
|
557
|
+
query.whereJsonSupersetOf("created_at", new Date());
|
|
558
|
+
// @ts-expect-error native PostgreSQL array columns are not JSON columns.
|
|
559
|
+
query.whereJsonSupersetOf("native_tags", ["urgent"]);
|
|
560
|
+
// @ts-expect-error vector columns are not JSON columns.
|
|
561
|
+
query.whereJsonSupersetOf("embedding", [0.1, 0.2]);
|
|
562
|
+
// @ts-expect-error scalar JSON roots retain their scalar type.
|
|
563
|
+
query.whereJsonSupersetOf("json_scalar", { state: "active" });
|
|
564
|
+
// @ts-expect-error top-level null is rejected even when the JSON column itself is nullable.
|
|
565
|
+
query.whereJsonSupersetOf("nullable_payload", null);
|
|
566
|
+
// @ts-expect-error top-level undefined is not JSON-serializable.
|
|
567
|
+
query.whereJsonSupersetOf("preferences", undefined);
|
|
568
|
+
// @ts-expect-error unknown must be narrowed before calling the public method.
|
|
569
|
+
query.whereJsonSupersetOf("preferences", unknownValue);
|
|
570
|
+
// @ts-expect-error top-level OR is intentionally exposed only through whereGroup.
|
|
571
|
+
query.orWhereJsonSupersetOf("preferences", { theme: "light" });
|
|
572
|
+
});
|
|
573
|
+
});
|
|
574
|
+
|
|
461
575
|
describe("Puri locking methods", () => {
|
|
462
576
|
it("forUpdate 체이닝 후 first 결과 타입을 유지한다", () => {
|
|
463
577
|
type Query = Puri<MockSchema, { users: MockSchema["users"] }, MockSchema["users"]>;
|
|
@@ -16,6 +16,7 @@ type LeftJoinedKey = "__leftJoined__";
|
|
|
16
16
|
type HasDefault = "__hasDefault__";
|
|
17
17
|
type GeneratedKey = "__generated__";
|
|
18
18
|
type VectorKey = "__vector__";
|
|
19
|
+
type JsonKey = "__json__";
|
|
19
20
|
type VirtualQueryKey = "__virtual_query__";
|
|
20
21
|
|
|
21
22
|
type InternalTypeKeys =
|
|
@@ -25,6 +26,7 @@ type InternalTypeKeys =
|
|
|
25
26
|
| HasDefault
|
|
26
27
|
| GeneratedKey
|
|
27
28
|
| VectorKey
|
|
29
|
+
| JsonKey
|
|
28
30
|
| VirtualQueryKey;
|
|
29
31
|
|
|
30
32
|
// ============================================
|
|
@@ -42,6 +44,23 @@ export type VectorColumns<TTables extends Record<string, any>> =
|
|
|
42
44
|
}[keyof TTables]
|
|
43
45
|
| (IsSingleKey<TTables> extends true ? VectorColumnKeys<TTables[keyof TTables]> : never);
|
|
44
46
|
|
|
47
|
+
// __json__ 메타데이터에서 JSON 컬럼 추출
|
|
48
|
+
type JsonColumnKeys<T> = T extends { [K in JsonKey]: readonly (infer J)[] } ? J & string : never;
|
|
49
|
+
|
|
50
|
+
export type JsonColumns<TTables extends Record<string, any>> =
|
|
51
|
+
| {
|
|
52
|
+
[TAlias in keyof TTables]: `${TAlias & string}.${JsonColumnKeys<TTables[TAlias]>}`;
|
|
53
|
+
}[keyof TTables]
|
|
54
|
+
| (IsSingleKey<TTables> extends true ? JsonColumnKeys<TTables[keyof TTables]> : never);
|
|
55
|
+
|
|
56
|
+
type JsonSupersetNestedValue<T> = T extends readonly (infer Element)[]
|
|
57
|
+
? JsonSupersetNestedValue<Element>[]
|
|
58
|
+
: T extends object
|
|
59
|
+
? { [K in keyof T]?: JsonSupersetNestedValue<T[K]> }
|
|
60
|
+
: T;
|
|
61
|
+
|
|
62
|
+
export type JsonSupersetValue<T> = JsonSupersetNestedValue<NonNullable<T>>;
|
|
63
|
+
|
|
45
64
|
// 테이블명 타입
|
|
46
65
|
export type TableName<TSchema> = keyof TSchema & string;
|
|
47
66
|
|
|
@@ -42,6 +42,12 @@ function getSocketPath(): string {
|
|
|
42
42
|
: join(homedir(), ".sonamu", `naite-${hash}.sock`);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
/**
|
|
46
|
+
* 연결 실패가 지속될 때(extension 미실행 등) buffer가 무한히 커지지 않도록
|
|
47
|
+
* 최근 메시지만 이 개수만큼 유지합니다.
|
|
48
|
+
*/
|
|
49
|
+
const MAX_BUFFERED_MESSAGES = 1000;
|
|
50
|
+
|
|
45
51
|
class NaiteReporterClass {
|
|
46
52
|
private socketPath: string | null = null;
|
|
47
53
|
private socket: Socket | null = null;
|
|
@@ -97,8 +103,11 @@ class NaiteReporterClass {
|
|
|
97
103
|
if (this.connected && this.socket) {
|
|
98
104
|
this.socket.write(msg);
|
|
99
105
|
} else {
|
|
100
|
-
// 연결 대기 중이면 버퍼에
|
|
106
|
+
// 연결 대기 중이면 버퍼에 저장, 상한 초과 시 오래된 메시지부터 폐기
|
|
101
107
|
this.buffer.push(msg);
|
|
108
|
+
if (this.buffer.length > MAX_BUFFERED_MESSAGES) {
|
|
109
|
+
this.buffer.shift();
|
|
110
|
+
}
|
|
102
111
|
}
|
|
103
112
|
}
|
|
104
113
|
|
|
@@ -171,6 +171,34 @@ db.where("status", "active").orWhereGroup((g) => {
|
|
|
171
171
|
});
|
|
172
172
|
```
|
|
173
173
|
|
|
174
|
+
### JSONB Containment (`@>`)
|
|
175
|
+
|
|
176
|
+
Use `whereJsonSupersetOf()` to require a JSONB column to contain a JSON value. The column and
|
|
177
|
+
containment value are checked against the generated Entity type, and the value is serialized and
|
|
178
|
+
bound internally.
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
db.table("products").whereJsonSupersetOf("metadata", { warranty: 2 });
|
|
182
|
+
|
|
183
|
+
// Aliased columns are supported.
|
|
184
|
+
db.table({ p: "products" }).whereJsonSupersetOf("p.metadata", {
|
|
185
|
+
tags: ["featured"],
|
|
186
|
+
});
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Inside a WHERE group, both AND and OR variants are available:
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
db.whereGroup((g) => {
|
|
193
|
+
g.where("status", "active").orWhereJsonSupersetOf("metadata", {
|
|
194
|
+
tags: ["featured"],
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Do not call `JSON.stringify()` yourself. For other JSONB operators such as `->>`, `->`, and `?`,
|
|
200
|
+
continue to use parameterized `whereRaw()`.
|
|
201
|
+
|
|
174
202
|
## JOIN
|
|
175
203
|
|
|
176
204
|
```typescript
|
|
@@ -62,6 +62,8 @@ async function registerEntityWithFileCustomScalar() {
|
|
|
62
62
|
table: `generated_template_file_${entitySeq}`,
|
|
63
63
|
props: [
|
|
64
64
|
{ name: "id", type: "integer" as const },
|
|
65
|
+
{ name: "title", type: "string" as const },
|
|
66
|
+
{ name: "created_at", type: "date" as const },
|
|
65
67
|
{
|
|
66
68
|
name: "file_props",
|
|
67
69
|
type: "json" as const,
|
|
@@ -70,7 +72,7 @@ async function registerEntityWithFileCustomScalar() {
|
|
|
70
72
|
],
|
|
71
73
|
indexes: [],
|
|
72
74
|
subsets: {
|
|
73
|
-
A: ["id", "file_props"],
|
|
75
|
+
A: ["id", "title", "created_at", "file_props"],
|
|
74
76
|
},
|
|
75
77
|
enums: {},
|
|
76
78
|
};
|
|
@@ -82,7 +84,7 @@ async function registerEntityWithFileCustomScalar() {
|
|
|
82
84
|
image: SonamuFileSchema.nullable(),
|
|
83
85
|
});
|
|
84
86
|
|
|
85
|
-
return { typeId };
|
|
87
|
+
return { entity: registeredEntity, typeId };
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
describe("Template__generated searchText", () => {
|
|
@@ -151,3 +153,16 @@ describe("Template__generated searchText", () => {
|
|
|
151
153
|
);
|
|
152
154
|
});
|
|
153
155
|
});
|
|
156
|
+
|
|
157
|
+
describe("Template__generated JSON metadata", () => {
|
|
158
|
+
test("only type=json properties appear in readonly __json__", async () => {
|
|
159
|
+
const { entity } = await registerEntityWithFileCustomScalar();
|
|
160
|
+
const template = new Template__generated();
|
|
161
|
+
|
|
162
|
+
const source = template.getBaseSchemaSourceCode(entity).lines.join("\n");
|
|
163
|
+
|
|
164
|
+
expect(source).toContain('readonly __json__: readonly ["file_props"],');
|
|
165
|
+
expect(source).not.toContain('readonly __json__: readonly ["title"');
|
|
166
|
+
expect(source).not.toContain('readonly __json__: readonly ["created_at"');
|
|
167
|
+
});
|
|
168
|
+
});
|
|
@@ -215,6 +215,14 @@ export class Template__generated extends Template {
|
|
|
215
215
|
.filter((prop) => prop.type === "vector" || prop.type === "vector[]")
|
|
216
216
|
.map((prop) => prop.name);
|
|
217
217
|
|
|
218
|
+
/**
|
|
219
|
+
* JSON props
|
|
220
|
+
* - json 타입인 컬럼
|
|
221
|
+
*/
|
|
222
|
+
const jsonColumns = entity.props
|
|
223
|
+
.filter((prop) => prop.type === "json")
|
|
224
|
+
.map((prop) => prop.name);
|
|
225
|
+
|
|
218
226
|
/**
|
|
219
227
|
* generated props
|
|
220
228
|
* - generated 속성이 있는 컬럼 (INSERT/UPDATE 시 값 제공 불가)
|
|
@@ -232,7 +240,8 @@ export class Template__generated extends Template {
|
|
|
232
240
|
virtualQueryProps.length > 0 ||
|
|
233
241
|
hasDefaultColumns.length > 0 ||
|
|
234
242
|
generatedColumns.length > 0 ||
|
|
235
|
-
hasVectorColumns.length > 0
|
|
243
|
+
hasVectorColumns.length > 0 ||
|
|
244
|
+
jsonColumns.length > 0;
|
|
236
245
|
|
|
237
246
|
const lines = [
|
|
238
247
|
`export const ${schemaName} = ${schemaBody};`,
|
|
@@ -264,6 +273,11 @@ export class Template__generated extends Template {
|
|
|
264
273
|
? `readonly __vector__: readonly [${hasVectorColumns
|
|
265
274
|
.map((col) => `"${col}"`)
|
|
266
275
|
.join(", ")}],`
|
|
276
|
+
: "") +
|
|
277
|
+
(jsonColumns.length > 0
|
|
278
|
+
? `readonly __json__: readonly [${jsonColumns
|
|
279
|
+
.map((col) => `"${col}"`)
|
|
280
|
+
.join(", ")}],`
|
|
267
281
|
: "")
|
|
268
282
|
}}`
|
|
269
283
|
: "") +
|