From 0df7fa4d45712f57dfe207f4b54e2e5cc263271c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BC=96=E7=A0=81=E7=8C=BF?= Date: Fri, 29 Aug 2025 22:03:56 +0800 Subject: [PATCH] 233 --- .DS_Store | Bin 6148 -> 6148 bytes .idea/workspace.xml | 53 +++++---- app/src/config/index.ts | 10 +- gateway/.DS_Store | Bin 6148 -> 6148 bytes gateway/.pydio | 1 - gateway/.yo-rc.json | 1 + gateway/config/.pydio | 1 - gateway/config/backup/.pydio | 1 - gateway/config/backup/gateway.config.yml | 80 ------------- gateway/config/gateway.config.json | 103 ----------------- gateway/config/gateway.config.yml | 32 +++++ gateway/config/models/.pydio | 1 - gateway/config/system.config.json | 27 ----- gateway/config/{backup => }/system.config.yml | 0 gateway/package.json | 14 +-- gateway/server.js | 6 + gateway/server.ts | 15 --- gateway/tsconfig.json | 109 ------------------ services/.DS_Store | Bin 6148 -> 0 bytes services/.pydio | 1 - 笔记.txt | 4 +- 21 files changed, 83 insertions(+), 376 deletions(-) delete mode 100644 gateway/.pydio create mode 100644 gateway/.yo-rc.json delete mode 100644 gateway/config/.pydio delete mode 100644 gateway/config/backup/.pydio delete mode 100644 gateway/config/backup/gateway.config.yml delete mode 100644 gateway/config/gateway.config.json create mode 100644 gateway/config/gateway.config.yml delete mode 100644 gateway/config/models/.pydio delete mode 100644 gateway/config/system.config.json rename gateway/config/{backup => }/system.config.yml (100%) create mode 100644 gateway/server.js delete mode 100644 gateway/server.ts delete mode 100644 gateway/tsconfig.json delete mode 100644 services/.DS_Store delete mode 100644 services/.pydio diff --git a/.DS_Store b/.DS_Store index 9c176f457b8f6a39689619c95bb5f0a98c3395a9..1b0d8150bed617d0235054e21cc33c156d3ec37c 100644 GIT binary patch delta 499 zcmZoMXfc@J&ndycz`)4BAi%IOY9n(!0|SW9!l1{H&XCDal9O&2oSdIq02Bj)hwVTD zE|;6{;*yk;p9B=+IPt#2;APM;M^yO~yz&JZNM^GEbuuupP8ML1V3L|PS&K!AZHk(B zw{X;CFBTaXGlxZvv0!pHi=<6fI8Ze+Ln1=~Ljkfo1d_Z;grmUjfXgCW0g;{jfJKTi zVDfJkMW&WLljT_DbgE=_mP2*11O1)IP{NSPP!6OkbMq0pA*v>4uqrVzFihUSDl&Ni zD<9LR3qYm+(9N!%$Qp9EDv4O3*SfOqf{sW-~j-Uw!}xiG8C0 delta 386 zcmZoMXfc@JFD$~qz`)4BAi%(on3HZ8oSdIqurYBZb3I6$l|hdolOcs66(I){1pD>)`f4mF4Cm?7);oF`v<4axtqS)4H{jr?JYhxoDgRI(hN~R*}i)Sa}d! zC8h#~$pLI4lO@>rm~MRlGQ}p_v2n49e*vraV^cyf#U}T#@i7KWp3Nr9q-{ER7n>BD cS>gqdvA5V{V9Y;ka*V*>O<~;3&heKY02`QTyZ`_I diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 69bfb3a..21ef556 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,21 +5,20 @@ - - - - - - - - - - - + + + + + + + + + + - - - + + + + + - + { + "associatedIndex": 4 +} @@ -66,15 +67,17 @@ "RunOnceActivity.OpenProjectViewOnStart": "true", "RunOnceActivity.ShowReadmeOnStart": "true", "WebServerToolWindowFactoryState": "false", - "git-widget-placeholder": "master", - "javascript.nodejs.core.library.configured.version": "20.9.0", - "javascript.nodejs.core.library.typings.version": "20.9.0", + "dart.analysis.tool.window.visible": "false", + "git-widget-placeholder": "main", + "javascript.nodejs.core.library.configured.version": "21.6.1", + "javascript.nodejs.core.library.typings.version": "22.7.4", "node.js.detected.package.eslint": "true", "node.js.detected.package.tslint": "true", "node.js.selected.package.eslint": "(autodetect)", "node.js.selected.package.tslint": "(autodetect)", "nodejs_package_manager_path": "npm", - "ts.external.directory.path": "/Users/bmy/Desktop/microservices/app/node_modules/typescript/lib", + "settings.editor.selected.configurable": "preferences.lookFeel", + "ts.external.directory.path": "/Users/bmy/source/microservices/app/node_modules/typescript/lib", "vue.rearranger.settings.migration": "true" } }]]> @@ -83,6 +86,13 @@ + + + + + + @@ -92,6 +102,7 @@ diff --git a/app/src/config/index.ts b/app/src/config/index.ts index bf0f628..0854f1f 100644 --- a/app/src/config/index.ts +++ b/app/src/config/index.ts @@ -4,17 +4,17 @@ export default { name: 'gateway', id: 'gateway_id', tags: ['Api 网关'], - address: '192.168.31.203', + address: '192.168.31.8', port: 8080 }, { name: 'user', id: 'user_id', tags: ['user模块', '登录'], - address: '192.168.31.203', + address: '192.168.31.8', port: 3002, check: { - http: 'http://192.168.31.203:3002/user/health', + http: 'http://192.168.31.8:3002/user/health', interval: '10s', timeout: '5s', notes: '服务正常', @@ -24,10 +24,10 @@ export default { name: 'articles', id: 'articles_id', tags: ['articles模块', '文章'], - address: '192.168.31.203', + address: '192.168.31.8', port: 3003, check: { - http: 'http://192.168.31.203:3003/articles/health', + http: 'http://192.168.31.8:3003/articles/health', interval: '10s', timeout: '5s', notes: '服务正常', diff --git a/gateway/.DS_Store b/gateway/.DS_Store index a747677c91256670429b52b8f355c75182423ae0..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 100644 GIT binary patch delta 70 zcmZoMXfc=|#>AjHu~2NHo+1YW5HK<@2y9-+n8vnw1EUw?W_AvK4xj>{$am(+{342+ UKzW7)kiy9(Jj$D6L{=~Z04H+~3jhEB delta 217 zcmZoMXfc=|#>B`mF;Q%yo}wrV0|Nsi1A_nqLncFdPP$=ma(-^X#Kh(GAPF{xWQKf( zJccx6NuW3oNLK*~6#3kI7nh`*{3M__N0ImWIUOd)95L0T5L8o;0dfRqZUIm;5G>f3 pSi&~hK!jy8HwQNd(BT^szcWwf7g1zo0?H~(HWU%w>>;v;82}`qGIsy~ diff --git a/gateway/.pydio b/gateway/.pydio deleted file mode 100644 index 034387e..0000000 --- a/gateway/.pydio +++ /dev/null @@ -1 +0,0 @@ -7bf782e6-9f6f-4dc3-ba13-a17c02882f8b \ No newline at end of file diff --git a/gateway/.yo-rc.json b/gateway/.yo-rc.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/gateway/.yo-rc.json @@ -0,0 +1 @@ +{} diff --git a/gateway/config/.pydio b/gateway/config/.pydio deleted file mode 100644 index fa7d75a..0000000 --- a/gateway/config/.pydio +++ /dev/null @@ -1 +0,0 @@ -e7a720b3-b16e-4dc4-b31c-a9c87709ea20 \ No newline at end of file diff --git a/gateway/config/backup/.pydio b/gateway/config/backup/.pydio deleted file mode 100644 index 61ca152..0000000 --- a/gateway/config/backup/.pydio +++ /dev/null @@ -1 +0,0 @@ -da3d4927-dcc5-4dd3-b8e2-42b1cf9b5eaa \ No newline at end of file diff --git a/gateway/config/backup/gateway.config.yml b/gateway/config/backup/gateway.config.yml deleted file mode 100644 index f246e19..0000000 --- a/gateway/config/backup/gateway.config.yml +++ /dev/null @@ -1,80 +0,0 @@ -# https://www.express-gateway.io/docs/configuration/gateway.config.yml/ -# https://www.cnblogs.com/PLM-Teamcenter/p/16388583.html - -http: - port: 8080 -admin: - port: 9876 - host: localhost -# 指定具体的客户端 - 绑定域名和 被映射的接口地址 -apiEndpoints: - api: - host: localhost - paths: '/ip' - - user_client: - host: localhost - paths: - - /user - - /user/* - - articles_client: - host: localhost - paths: - - /articles - - /articles/* - -# 声明网关可以管理的微服务 - 被代理的地址 -serviceEndpoints: - userbin: - url: 'http://127.0.0.1:3002' - - articlesbin: - url: 'http://127.0.0.1:3003' - - httpbin: - url: 'https://httpbin.org' - -policies: - - basic-auth - - cors - - expression - - key-auth - - log - - oauth2 - - proxy - - rate-limit - -# 通过管道把客户端与微服务串联起来 -pipelines: - - default: - apiEndpoints: - - api - policies: - # Uncomment `key-auth:` when instructed to in the Getting Started guide. - # - key-auth: - # proxy;它的作用是代理/转发请求,这里指定了将 apiEndpoints 来的请求转发到前面定义了的微服务 - - proxy: - - action: - serviceEndpoint: httpbin - changeOrigin: true - - pipeline_user: - apiEndpoints: - - user_client - policies: - - proxy: - - action: - serviceEndpoint: userbin - changeOrigin: true - - pipeline_articles: - apiEndpoints: - - articles_client - policies: - - proxy: - - action: - serviceEndpoint: articlesbin - changeOrigin: true - diff --git a/gateway/config/gateway.config.json b/gateway/config/gateway.config.json deleted file mode 100644 index 1c42d46..0000000 --- a/gateway/config/gateway.config.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "http": { - "port": 8080 - }, - "admin": { - "port": 9876, - "host": "localhost" - }, - "apiEndpoints": { - "api": { - "host": "localhost", - "paths": "/ip" - }, - "user_client": { - "host": "localhost", - "paths": [ - "/user", - "/user/*" - ] - }, - "articles_client": { - "host": "localhost", - "paths": [ - "/articles", - "/articles/*" - ] - } - }, - "serviceEndpoints": { - "userbin": { - "url": "http://127.0.0.1:3002" - }, - "articlesbin": { - "url": "http://127.0.0.1:3003" - }, - "httpbin": { - "url": "https://httpbin.org" - } - }, - "policies": [ - "basic-auth", - "cors", - "expression", - "key-auth", - "log", - "oauth2", - "proxy", - "rate-limit" - ], - "pipelines": { - "default": { - "apiEndpoints": [ - "api" - ], - "policies": [ - { - "proxy": [ - { - "action": { - "serviceEndpoint": "httpbin", - "changeOrigin": true - } - } - ] - } - ] - }, - "pipeline_user": { - "apiEndpoints": [ - "user_client" - ], - "policies": [ - { - "proxy": [ - { - "action": { - "serviceEndpoint": "userbin", - "changeOrigin": true - } - } - ] - } - ] - }, - "pipeline_articles": { - "apiEndpoints": [ - "articles_client" - ], - "policies": [ - { - "proxy": [ - { - "action": { - "serviceEndpoint": "articlesbin", - "changeOrigin": true - } - } - ] - } - ] - } - } - } \ No newline at end of file diff --git a/gateway/config/gateway.config.yml b/gateway/config/gateway.config.yml new file mode 100644 index 0000000..63378f3 --- /dev/null +++ b/gateway/config/gateway.config.yml @@ -0,0 +1,32 @@ +http: + port: 8080 +admin: + port: 9876 + host: localhost +apiEndpoints: + api: + host: localhost + paths: '/ip' +serviceEndpoints: + httpbin: + url: 'https://httpbin.org' +policies: + - basic-auth + - cors + - expression + - key-auth + - log + - oauth2 + - proxy + - rate-limit +pipelines: + default: + apiEndpoints: + - api + policies: + # Uncomment `key-auth:` when instructed to in the Getting Started guide. + # - key-auth: + - proxy: + - action: + serviceEndpoint: httpbin + changeOrigin: true diff --git a/gateway/config/models/.pydio b/gateway/config/models/.pydio deleted file mode 100644 index 9aaaf7b..0000000 --- a/gateway/config/models/.pydio +++ /dev/null @@ -1 +0,0 @@ -dbd3cf03-e067-4aed-9f60-fbd5cc998830 \ No newline at end of file diff --git a/gateway/config/system.config.json b/gateway/config/system.config.json deleted file mode 100644 index a267809..0000000 --- a/gateway/config/system.config.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "db": { - "redis": { - "emulate": true, - "namespace": "EG" - } - }, - "crypto": { - "cipherKey": "sensitiveKey", - "algorithm": "aes256", - "saltRounds": 10 - }, - "session": { - "secret": "keyboard cat", - "resave": false, - "saveUninitialized": false - }, - "accessTokens": { - "timeToExpiry": 7200000 - }, - "refreshTokens": { - "timeToExpiry": 7200000 - }, - "authorizationCodes": { - "timeToExpiry": 300000 - } -} \ No newline at end of file diff --git a/gateway/config/backup/system.config.yml b/gateway/config/system.config.yml similarity index 100% rename from gateway/config/backup/system.config.yml rename to gateway/config/system.config.yml diff --git a/gateway/package.json b/gateway/package.json index f26a3ff..e75226c 100644 --- a/gateway/package.json +++ b/gateway/package.json @@ -1,15 +1,11 @@ { "name": "gateway", + "description": "Express Gateway Instance Bootstraped from Command Line", + "repository": {}, + "license": "UNLICENSED", "version": "1.0.0", - "description": "", - "main": "server.ts", - "scripts": { - "start": "ts-node server.ts" - }, - "keywords": [], - "author": "", - "license": "ISC", + "main": "server.js", "dependencies": { "express-gateway": "^1.16.11" } -} \ No newline at end of file +} diff --git a/gateway/server.js b/gateway/server.js new file mode 100644 index 0000000..c282d01 --- /dev/null +++ b/gateway/server.js @@ -0,0 +1,6 @@ +const path = require('path'); +const gateway = require('express-gateway'); + +gateway() + .load(path.join(__dirname, 'config')) + .run(); diff --git a/gateway/server.ts b/gateway/server.ts deleted file mode 100644 index 8ea528d..0000000 --- a/gateway/server.ts +++ /dev/null @@ -1,15 +0,0 @@ -const path = require('path'); -import { join } from "path"; -import gateway from "express-gateway"; -// const gateway = require('express-gateway'); - -class run { - constructor () { - //@ts-ignore - gateway() - .load(join(__dirname, 'config')) - .run(); - } -} - -new run() diff --git a/gateway/tsconfig.json b/gateway/tsconfig.json deleted file mode 100644 index 874945e..0000000 --- a/gateway/tsconfig.json +++ /dev/null @@ -1,109 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - - /* Modules */ - "module": "commonjs", /* Specify what module code is generated. */ - "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ - "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ - // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ - // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ - // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ - // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - "sourceMap": false, /* Create source map files for emitted JavaScript files. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - "outDir": "./dist", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - } -} diff --git a/services/.DS_Store b/services/.DS_Store deleted file mode 100644 index 5489dfa73765ba851cef718be04b678bc8d9e02d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKJ5Iwu5SChR#H$qVxrD90W+V93`Yga!JVnI1e>P;?2&;A8aHl zgrXT~_O0jRUB9(F9wKtf{W>OE5K#nWoSk5p5cac+c@sM##hnV^lvfH7bU zv<&d~!9y7n#YQlEIxvJ5062#^2nzK^u($V_?X@kz6jg{@?uE{|}Sw$`~*P4vGOcPqTE1N7C9l wdN{7N9(o65;kZVyO~E9TV#IPOzJLaS-SY&PC^mwyK