├── .editorconfig ├── .eslintrc.cjs ├── .gitea └── workflows │ └── build.yml ├── .github └── workflows │ └── build.yaml ├── .gitignore ├── .npmrc ├── .prettierrc.json ├── .swcrc ├── LICENSE ├── Makefile ├── README.md ├── apps ├── console │ ├── .env │ ├── .gitignore │ ├── .prettierignore │ ├── .prettierrc.json │ ├── .storybook │ │ ├── main.ts │ │ └── preview.tsx │ ├── Makefile │ ├── codegen.ts │ ├── graphql.config.yml │ ├── index.html │ ├── knip.jsonc │ ├── lib.d.ts │ ├── package.json │ ├── postcss.config.cjs │ ├── public │ │ ├── docs.html │ │ ├── favicon.ico │ │ ├── graphiql.html │ │ ├── logo.svg │ │ └── robots.txt │ ├── src │ │ ├── applets │ │ │ ├── Calculator │ │ │ │ ├── Calculator.tsx │ │ │ │ └── CalculatorWidget.tsx │ │ │ └── Playground │ │ │ │ ├── Playground.tsx │ │ │ │ └── PlaygroundWidget.tsx │ │ ├── assets │ │ │ ├── LoginSplash.jpg │ │ │ └── manifest.json │ │ ├── casl │ │ │ ├── Can.tsx │ │ │ ├── casl.test.ts │ │ │ ├── casl.ts │ │ │ ├── getUserAbility.ts │ │ │ └── index.ts │ │ ├── components │ │ │ ├── ProdOnly.tsx │ │ │ ├── WebVitals.tsx │ │ │ ├── props.d.ts │ │ │ └── useReportWebVitals.tsx │ │ ├── console │ │ │ ├── ConsoleApp.tsx │ │ │ ├── ConsoleAppContent.tsx │ │ │ ├── RootContext.tsx │ │ │ ├── RouteStore.tsx │ │ │ ├── base.init.ts │ │ │ ├── components │ │ │ │ ├── ConsoleLayout │ │ │ │ │ ├── ConsoleLayout.tsx │ │ │ │ │ ├── ConsoleLayoutContext.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── DockLayout │ │ │ │ │ ├── DockClock.tsx │ │ │ │ │ ├── DockLayout.stories.tsx │ │ │ │ │ ├── DockLayout.tsx │ │ │ │ │ ├── DockUserAvatar.tsx │ │ │ │ │ └── index.ts │ │ │ ├── createConsoleRoutes.tsx │ │ │ ├── createWorkRoutes.tsx │ │ │ ├── globals.css │ │ │ ├── loadModule.tsx │ │ │ ├── main.tsx │ │ │ ├── modules │ │ │ │ ├── site.core │ │ │ │ │ └── module.tsx │ │ │ │ └── user.core │ │ │ │ │ ├── SiteModules.tsx │ │ │ │ │ └── module.tsx │ │ │ ├── pages │ │ │ │ ├── DevDebugPage.tsx │ │ │ │ ├── HomePage.tsx │ │ │ │ ├── SettingPage.tsx │ │ │ │ ├── UserProfilePage.tsx │ │ │ │ └── UserSettingProfile.tsx │ │ │ └── routes │ │ │ │ ├── home.route.tsx │ │ │ │ ├── setting.appearance.route.tsx │ │ │ │ ├── setting.dev.debug.route.tsx │ │ │ │ ├── setting.profile.route.tsx │ │ │ │ ├── setting.route.tsx │ │ │ │ ├── setting.system.route.tsx │ │ │ │ └── user.$userId.route.tsx │ │ ├── const.ts │ │ ├── foundation │ │ │ ├── Auth │ │ │ │ ├── AuthActions.ts │ │ │ │ └── query.ts │ │ │ ├── Site │ │ │ │ ├── SiteActions.ts │ │ │ │ └── query.ts │ │ │ └── User │ │ │ │ ├── UserActions.ts │ │ │ │ └── query.ts │ │ ├── gql │ │ │ ├── fragment-masking.ts │ │ │ ├── gql.ts │ │ │ ├── graphql.ts │ │ │ ├── index.ts │ │ │ ├── persisted-documents.json │ │ │ └── urql.schema.json │ │ ├── hooks │ │ │ └── env.tsx │ │ ├── instance │ │ │ ├── Instance.tsx │ │ │ ├── WenerLogo.tsx │ │ │ ├── index.ts │ │ │ └── instance.init.ts │ │ ├── meta │ │ │ └── FileTypes.ts │ │ ├── resource │ │ │ ├── defineResource.tsx │ │ │ ├── defineResourceModule.tsx │ │ │ ├── index.ts │ │ │ ├── types │ │ │ │ ├── AnyResource.ts │ │ │ │ └── Identifiable.ts │ │ │ └── utils │ │ │ │ └── getTitleOfResource.tsx │ │ ├── scripts │ │ │ └── write-version.ts │ │ └── vite-env.d.ts │ ├── svgo.config.json │ ├── tailwind.config.ts │ ├── tsconfig.json │ ├── vite.config.ts │ └── vitest.config.ts ├── file-server │ ├── README.md │ └── package.json ├── server │ ├── .env │ ├── .swcrc │ ├── Makefile │ ├── README.md │ ├── builds │ │ ├── apis-open-server │ │ │ ├── Dockerfile │ │ │ ├── app │ │ │ │ └── .gitignore │ │ │ └── rootfs │ │ │ │ ├── app │ │ │ │ └── package.json │ │ │ │ └── root │ │ │ │ └── .npmrc │ │ ├── docker-bake.hcl │ │ ├── openai-proxy │ │ │ ├── Dockerfile │ │ │ ├── app │ │ │ │ └── .gitignore │ │ │ └── rootfs │ │ │ │ ├── app │ │ │ │ ├── .npmrc │ │ │ │ └── package.json │ │ │ │ └── root │ │ │ │ └── .npmrc │ │ └── wener-get-server │ │ │ ├── Dockerfile │ │ │ ├── app │ │ │ └── .gitignore │ │ │ └── rootfs │ │ │ ├── app │ │ │ ├── .npmrc │ │ │ └── package.json │ │ │ └── root │ │ │ └── .npmrc │ ├── db │ │ ├── demo │ │ │ └── migrations │ │ │ │ ├── 000100_public.base.sql │ │ │ │ ├── 000101_public.table_size.sql │ │ │ │ ├── 000102_public.ulid.sql │ │ │ │ ├── 000500_tenant.sql │ │ │ │ ├── 100001_dict.sql │ │ │ │ ├── 100005_audit_log.sql │ │ │ │ ├── 100006_access_token.sql │ │ │ │ └── 100010_0_user.sql │ │ └── legacy │ │ │ └── migrations │ │ │ ├── 100110_entity.sql │ │ │ ├── 100197_file_content.sql │ │ │ ├── 100201_http_request_log.sql │ │ │ ├── 100203_client_agent.sql │ │ │ └── 101010_storage_item.sql │ ├── docs │ │ ├── reference │ │ │ ├── includes │ │ │ │ ├── _apis-open-server.md │ │ │ │ └── _errors.md │ │ │ └── index.html.md │ │ └── widdershins │ │ │ └── templates │ │ │ └── openapi3 │ │ │ ├── README.md │ │ │ ├── authentication.def │ │ │ ├── authentication_none.def │ │ │ ├── callbacks.def │ │ │ ├── code_csharp.dot │ │ │ ├── code_go.dot │ │ │ ├── code_http.dot │ │ │ ├── code_java.dot │ │ │ ├── code_javascript.dot │ │ │ ├── code_jquery.dot │ │ │ ├── code_nodejs.dot │ │ │ ├── code_php.dot │ │ │ ├── code_python.dot │ │ │ ├── code_ruby.dot │ │ │ ├── code_shell.dot │ │ │ ├── debug.def │ │ │ ├── discovery.def │ │ │ ├── footer.def │ │ │ ├── links.def │ │ │ ├── main.dot │ │ │ ├── operation.dot │ │ │ ├── parameters.def │ │ │ ├── responses.def │ │ │ ├── security.def │ │ │ └── translations.dot │ ├── lib.d.ts │ ├── package.json │ ├── package.mk │ ├── public │ │ ├── docs.html │ │ ├── graphiql.html │ │ └── robots.txt │ ├── src │ │ ├── app │ │ │ ├── InjectToken.ts │ │ │ ├── actuator │ │ │ │ ├── actuator.module.ts │ │ │ │ ├── const.ts │ │ │ │ ├── env.controller.ts │ │ │ │ ├── health.controller.ts │ │ │ │ └── process.controller.ts │ │ │ ├── app.context.ts │ │ │ ├── app.run.ts │ │ │ ├── auth │ │ │ │ ├── AuthPrincipal.ts │ │ │ │ ├── auth.controller.ts │ │ │ │ ├── auth.decorator.ts │ │ │ │ ├── auth.guard.ts │ │ │ │ ├── auth.module.ts │ │ │ │ ├── auth.service.ts │ │ │ │ ├── check-policies.decorator.ts │ │ │ │ ├── getRequest.ts │ │ │ │ ├── index.ts │ │ │ │ ├── policies.guard.ts │ │ │ │ ├── public.decorator.ts │ │ │ │ ├── role.enum.ts │ │ │ │ ├── roles.decorator.ts │ │ │ │ └── roles.guard.ts │ │ │ ├── bootstrap.ts │ │ │ ├── config │ │ │ │ ├── database.config.ts │ │ │ │ ├── index.ts │ │ │ │ ├── redis.config.ts │ │ │ │ ├── root.config.ts │ │ │ │ └── server.config.ts │ │ │ ├── core.module.ts │ │ │ ├── dayjs.tsx │ │ │ ├── decorator │ │ │ │ ├── cookies.decorator.ts │ │ │ │ └── index.ts │ │ │ ├── filter │ │ │ │ └── axios.filter.ts │ │ │ ├── graphql │ │ │ │ ├── GraphQLCoreModule.ts │ │ │ │ └── index.ts │ │ │ ├── hook.module.ts │ │ │ ├── index.ts │ │ │ ├── loader.module.ts │ │ │ ├── middleware │ │ │ │ └── server-middleware.service.ts │ │ │ ├── mikro-orm │ │ │ │ ├── context.ts │ │ │ │ ├── createMikroOrmConfig.ts │ │ │ │ ├── entity │ │ │ │ │ ├── EnumBaseEntity.ts │ │ │ │ │ ├── MinimalBaseEntity.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ └── mikro-orm.filter.ts │ │ │ ├── run │ │ │ │ └── index.ts │ │ │ ├── server.module.ts │ │ │ ├── types.ts │ │ │ └── util │ │ │ │ ├── getStaticRootPath.ts │ │ │ │ └── requireFound.ts │ │ ├── apps │ │ │ ├── wode-api-server │ │ │ │ ├── getInstanceGraphModule.ts │ │ │ │ ├── main.ts │ │ │ │ ├── runServer.ts │ │ │ │ └── setupDayjs.ts │ │ │ └── wode-service-agent │ │ │ │ ├── main.ts │ │ │ │ └── runServiceAgent.ts │ │ ├── const.ts │ │ ├── entity │ │ │ ├── AccessTokenEntity.ts │ │ │ ├── BaseTenantDictEntity.ts │ │ │ ├── ClientAgentEntity.ts │ │ │ ├── FileContentEntity.ts │ │ │ ├── HttpRequestLogEntity.ts │ │ │ ├── StorageItemEntity.ts │ │ │ └── base │ │ │ │ ├── StandardBaseEntity.ts │ │ │ │ ├── SystemBaseEntity.ts │ │ │ │ ├── enum.ts │ │ │ │ ├── setData.ts │ │ │ │ └── xtypes.ts │ │ ├── foundation │ │ │ ├── Audit │ │ │ │ ├── AuditLogEntity.ts │ │ │ │ ├── AuditModule.ts │ │ │ │ ├── AuditService.ts │ │ │ │ ├── collectAuditData.ts │ │ │ │ ├── enum.ts │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ ├── writeAuditLog.ts │ │ │ │ ├── writeEntityAuditLog.ts │ │ │ │ ├── writeSystemAuditLog.ts │ │ │ │ └── writeUserAuditLog.ts │ │ │ ├── Auth │ │ │ │ ├── AccessControlService.ts │ │ │ │ ├── AccessTokenService.ts │ │ │ │ ├── AuthPermissionService.ts │ │ │ │ ├── AuthRoleService.ts │ │ │ │ ├── AuthService.ts │ │ │ │ ├── entity │ │ │ │ │ ├── AccessTokenEntity.ts │ │ │ │ │ ├── AuthEntityPermissionEntity.ts │ │ │ │ │ ├── AuthEntityRoleEntity.ts │ │ │ │ │ ├── AuthPermissionEntity.ts │ │ │ │ │ ├── AuthRoleEntity.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── withRolesEntity.ts │ │ │ │ └── graph │ │ │ │ │ ├── AccessControlResolver.ts │ │ │ │ │ └── AuthResolver.ts │ │ │ ├── Resource │ │ │ │ └── graph │ │ │ │ │ ├── EntityResolver.ts │ │ │ │ │ └── RelayNodeResolver.ts │ │ │ ├── ResourceOwner │ │ │ │ └── OwnerNode.ts │ │ │ ├── System │ │ │ │ ├── SystemService.ts │ │ │ │ └── graph │ │ │ │ │ ├── PingResolver.ts │ │ │ │ │ ├── SiteResolver.ts │ │ │ │ │ └── SystemResolver.ts │ │ │ ├── Tenant │ │ │ │ ├── TenantService.ts │ │ │ │ ├── const.ts │ │ │ │ ├── entity │ │ │ │ │ └── TenantEntity.ts │ │ │ │ ├── index.ts │ │ │ │ ├── matchTenantFromHost.test.ts │ │ │ │ └── matchTenantFromHost.ts │ │ │ ├── User │ │ │ │ ├── UserService.ts │ │ │ │ ├── entity │ │ │ │ │ └── UserEntity.ts │ │ │ │ ├── graph │ │ │ │ │ └── UserResolver.ts │ │ │ │ └── password.ts │ │ │ ├── entity │ │ │ │ ├── ContactMethodType.ts │ │ │ │ ├── GenderTypeEntity.ts │ │ │ │ └── LicenseTypeEntity.ts │ │ │ ├── jobs │ │ │ │ ├── runSystemMaintenance.ts │ │ │ │ └── runSystemResourceImportSeed.ts │ │ │ ├── meta │ │ │ │ ├── defineEntitySeed.ts │ │ │ │ └── defineSystemModule.ts │ │ │ └── services │ │ │ │ ├── CustomAutoEntityService.ts │ │ │ │ └── CustomBaseEntityService.tsx │ │ ├── graph │ │ │ ├── HasCustomerNode.ts │ │ │ ├── HasRoleObject.ts │ │ │ ├── ResourceNode.ts │ │ │ ├── TenantBaseObject.ts │ │ │ ├── common.ts │ │ │ ├── const.ts │ │ │ ├── getPubSub.ts │ │ │ └── utils │ │ │ │ ├── resolveNodeType.ts │ │ │ │ └── runMutation.ts │ │ ├── modules │ │ │ ├── FetchCache │ │ │ │ ├── BaseHttpRequestLogEntity.ts │ │ │ │ ├── FetchCache.ts │ │ │ │ ├── HttpRequestLog.ts │ │ │ │ ├── SSE.ts │ │ │ │ ├── createFetchWithCache.ts │ │ │ │ ├── findHttpRequestCache.ts │ │ │ │ ├── index.ts │ │ │ │ ├── removeNullChar.test.ts │ │ │ │ ├── removeNullChar.ts │ │ │ │ └── up.sql │ │ │ ├── README.md │ │ │ ├── common │ │ │ │ └── dto │ │ │ │ │ ├── FindQuery.ts │ │ │ │ │ ├── FindResult.ts │ │ │ │ │ ├── GeneralResponse.dto.ts │ │ │ │ │ └── index.ts │ │ │ └── fetch-cache │ │ │ │ ├── FetchCache.ts │ │ │ │ ├── HttpRequestLog.repository.ts │ │ │ │ ├── HttpRequestLog.ts │ │ │ │ ├── SSE.ts │ │ │ │ ├── const.ts │ │ │ │ ├── createFetchWithCache.ts │ │ │ │ ├── db │ │ │ │ └── migrations │ │ │ │ │ └── up.sql │ │ │ │ ├── fetch-cache.module.ts │ │ │ │ ├── fetch-cache.service.ts │ │ │ │ ├── index.ts │ │ │ │ ├── removeNullChar.test.ts │ │ │ │ ├── removeNullChar.ts │ │ │ │ └── request.controller.ts │ │ ├── scripts │ │ │ └── bundle.esbuild.ts │ │ ├── server │ │ │ ├── connect │ │ │ │ └── serveNodeConnect.ts │ │ │ ├── context.ts │ │ │ ├── events │ │ │ │ ├── EntityEventRelaySubscriber.ts │ │ │ │ ├── events.ts │ │ │ │ ├── getRemoteEvents.ts │ │ │ │ ├── handleRemoteSystemEvents.ts │ │ │ │ ├── handleSystemEventRelay.ts │ │ │ │ ├── index.ts │ │ │ │ └── runRemoteEventHandler.ts │ │ │ ├── hono │ │ │ │ ├── withHonoAuth.ts │ │ │ │ └── withHonoContext.ts │ │ │ ├── proxy │ │ │ │ ├── dropProxyHeaders.ts │ │ │ │ ├── resolveProxyExternalUrl.ts │ │ │ │ └── serveExternalProxy.ts │ │ │ ├── redis │ │ │ │ ├── context.ts │ │ │ │ ├── parseRedisOptions.test.ts │ │ │ │ ├── parseRedisOptions.ts │ │ │ │ └── redis.ts │ │ │ ├── routes │ │ │ │ └── createBaseRoute.ts │ │ │ ├── utils │ │ │ │ ├── resolveProvides.ts │ │ │ │ ├── resolveRequestToken.ts │ │ │ │ └── runContext.ts │ │ │ └── yoga │ │ │ │ ├── buildGraphModule.ts │ │ │ │ ├── buildGraphQLSchema.ts │ │ │ │ ├── createYogaServer.ts │ │ │ │ └── serveYoga.ts │ │ ├── services │ │ │ └── AgentConnectService.ts │ │ ├── util │ │ │ ├── JWTPayload.ts │ │ │ ├── createFetchWithProxyByUndici.ts │ │ │ ├── fetch-proxy.test.ts │ │ │ ├── getPackageDir.ts │ │ │ ├── requireDefined.ts │ │ │ └── requireResponseOk.ts │ │ └── utils │ │ │ ├── decorator │ │ │ └── FieldSchema.ts │ │ │ ├── getCacheFile.ts │ │ │ ├── orm │ │ │ ├── loadEntity.ts │ │ │ ├── patchMikroORMMetadataStorage.polyfill.ts │ │ │ └── scanEntity.ts │ │ │ ├── serveFile.ts │ │ │ ├── strip.test.ts │ │ │ └── strip.ts │ ├── tsconfig.json │ ├── vite.config.ts │ └── vitest.config.ts ├── web │ ├── .env │ ├── .env.production │ ├── .prettierignore │ ├── Makefile │ ├── codegen.ts │ ├── graphql.config.yml │ ├── lingui.config.ts │ ├── next-env.d.ts │ ├── next.config.mjs │ ├── package.json │ ├── postcss.config.cjs │ ├── public │ │ ├── logo.svg │ │ └── robots.txt │ ├── src │ │ ├── app │ │ │ ├── NextRootLayout.tsx │ │ │ ├── children │ │ │ │ └── riddle │ │ │ │ │ └── print │ │ │ │ │ └── page.tsx │ │ │ ├── cn │ │ │ │ └── id │ │ │ │ │ └── page.tsx │ │ │ ├── daisy │ │ │ │ └── theme │ │ │ │ │ ├── DaisyThemePage.tsx │ │ │ │ │ └── page.tsx │ │ │ ├── error.tsx │ │ │ ├── eta │ │ │ │ └── render │ │ │ │ │ ├── EtaRenderPage.tsx │ │ │ │ │ └── page.tsx │ │ │ ├── favicon.ico │ │ │ ├── globals.css │ │ │ ├── hash │ │ │ │ └── page.tsx │ │ │ ├── icon.png │ │ │ ├── id │ │ │ │ └── benchmark │ │ │ │ │ ├── IdBenchmarkPage.tsx │ │ │ │ │ └── page.tsx │ │ │ ├── ipfs │ │ │ │ └── gateway │ │ │ │ │ └── check │ │ │ │ │ └── page.tsx │ │ │ ├── layout.tsx │ │ │ ├── nordvpn │ │ │ │ ├── country │ │ │ │ │ └── page.tsx │ │ │ │ ├── data.ts │ │ │ │ ├── layout.tsx │ │ │ │ ├── page.tsx │ │ │ │ └── server │ │ │ │ │ └── page.tsx │ │ │ ├── not-found.tsx │ │ │ ├── page.tsx │ │ │ ├── password │ │ │ │ ├── hash │ │ │ │ │ ├── PasswordHashContent.tsx │ │ │ │ │ └── page.tsx │ │ │ │ ├── layout.tsx │ │ │ │ ├── page.tsx │ │ │ │ └── strength │ │ │ │ │ └── page.tsx │ │ │ ├── semver │ │ │ │ └── page.tsx │ │ │ ├── sucrase │ │ │ │ └── transform │ │ │ │ │ ├── SucraseTransformPage.tsx │ │ │ │ │ └── page.tsx │ │ │ ├── utils.ts │ │ │ └── web │ │ │ │ ├── Intl.Segmenter │ │ │ │ └── page.tsx │ │ │ │ └── html-to-react │ │ │ │ ├── HtmlToReactPage.tsx │ │ │ │ └── page.tsx │ │ ├── components │ │ │ ├── ContentContainer.tsx │ │ │ ├── FootNote.tsx │ │ │ ├── FootNoteLink.tsx │ │ │ ├── NotFoundPlaceholder.tsx │ │ │ ├── SearchBox.tsx │ │ │ ├── SearchPageLayout.tsx │ │ │ ├── bookmark │ │ │ │ └── parseBookmark.ts │ │ │ ├── children │ │ │ │ └── RiddlePrintPage.tsx │ │ │ ├── cn │ │ │ │ ├── ChinaCitizenIdDescription.tsx │ │ │ │ ├── ChinaIdInfoPage.tsx │ │ │ │ ├── Formats.tsx │ │ │ │ ├── ParserCard.tsx │ │ │ │ ├── Parsers.ts │ │ │ │ ├── UnifiedSocialCreditIdDescription.tsx │ │ │ │ ├── code.ts │ │ │ │ ├── gb11643 │ │ │ │ │ ├── ChinaCitizenId.test.ts │ │ │ │ │ ├── ChinaCitizenId.ts │ │ │ │ │ ├── mod11.ts │ │ │ │ │ └── mode11.test.ts │ │ │ │ ├── gb31200 │ │ │ │ │ ├── UnifiedSocialCreditId.test.ts │ │ │ │ │ ├── UnifiedSocialCreditId.ts │ │ │ │ │ ├── mod31.test.ts │ │ │ │ │ └── mod31.ts │ │ │ │ ├── gs15 │ │ │ │ │ ├── BusinessLicenseNo.test.ts │ │ │ │ │ └── BusinessLicenseNo.ts │ │ │ │ ├── parseIt.ts │ │ │ │ ├── parsers │ │ │ │ │ ├── ULID.ts │ │ │ │ │ └── UUID.ts │ │ │ │ ├── usci │ │ │ │ │ ├── checkUSCI.ts │ │ │ │ │ ├── mod31.ts │ │ │ │ │ ├── randomUSCI.ts │ │ │ │ │ ├── usci.test.ts │ │ │ │ │ └── usci.ts │ │ │ │ └── utils │ │ │ │ │ └── randomPick.ts │ │ │ ├── getContextStates.ts │ │ │ ├── hash │ │ │ │ └── HashPage.tsx │ │ │ ├── home │ │ │ │ └── HomePage.tsx │ │ │ ├── ipfs │ │ │ │ ├── IpfsAccess.tsx │ │ │ │ ├── IpfsPage.tsx │ │ │ │ ├── buildIpfsLink.ts │ │ │ │ ├── createIpfsRoutes.tsx │ │ │ │ ├── gateway.ts │ │ │ │ └── gateway │ │ │ │ │ ├── IpfsGatewayCheck.tsx │ │ │ │ │ ├── IpfsGatewaySetting.tsx │ │ │ │ │ ├── checker.ts │ │ │ │ │ └── getIpfsPublicGateways.ts │ │ │ ├── page │ │ │ │ ├── PageContainer.tsx │ │ │ │ ├── PageLayout │ │ │ │ │ ├── LanguageSwitch.tsx │ │ │ │ │ ├── PageLayout.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── TabPageLayout.tsx │ │ │ ├── resolveActiveProps.ts │ │ │ ├── semver │ │ │ │ └── SemverTool.tsx │ │ │ ├── site │ │ │ │ └── SiteSidecar.tsx │ │ │ ├── spec │ │ │ │ └── IntlSegmenterPage.tsx │ │ │ └── zxcvbn │ │ │ │ ├── ZxcvbnNote.tsx │ │ │ │ └── ZxcvbnPasswordStrength.tsx │ │ ├── const.ts │ │ ├── data │ │ │ ├── const.tsx │ │ │ ├── defineEntry.tsx │ │ │ ├── getSiteData.ts │ │ │ └── riddle.json │ │ ├── i18n │ │ │ ├── I18nServerProvider.tsx │ │ │ ├── LinguiClientProvider.tsx │ │ │ ├── getLocales.ts │ │ │ ├── index.tsx │ │ │ ├── loadI18n.ts │ │ │ ├── loadMessage.ts │ │ │ ├── resolveClientLocale.tsx │ │ │ ├── resolveCurrentLocale.tsx │ │ │ ├── resolveLocale.test.ts │ │ │ ├── resolveLocale.ts │ │ │ └── resolveRequestLocale.tsx │ │ ├── locales │ │ │ ├── en │ │ │ │ ├── messages.mjs │ │ │ │ └── messages.po │ │ │ └── zh-CN │ │ │ │ ├── messages.mjs │ │ │ │ └── messages.po │ │ ├── middleware.ts │ │ ├── next │ │ │ └── NavLink.tsx │ │ ├── server │ │ │ └── createServerContext.ts │ │ └── types.ts │ ├── tailwind.config.ts │ ├── tsconfig.json │ └── vitest.config.ts └── woodpecker-feishu-bot │ └── README.md ├── base.mk ├── buf.gen.yaml ├── buf.yaml ├── components └── wener-tiptap │ ├── .npmignore │ ├── Makefile │ ├── index.ts │ ├── package.json │ ├── rollup.bundle.mjs │ ├── rollup.dev.mjs │ ├── src │ ├── extensions │ │ ├── BoldExtension.ts │ │ ├── ClassNameExtension.ts │ │ ├── ColorHighlighterExtension.ts │ │ ├── CssColumnsExtension.ts │ │ ├── DefaultMarkdownExtensionOptions.ts │ │ ├── Extensions.ts │ │ ├── ImageNode.ts │ │ ├── ItalicExtension.ts │ │ ├── MarkdownExtension.ts │ │ ├── SmileReplacer.ts │ │ ├── StrikeExtension.ts │ │ ├── TaskListExtension.ts │ │ ├── TextStyleExtension.ts │ │ ├── TipTapWordStarterKit.ts │ │ ├── UnderlineExtension.ts │ │ ├── VideoNode.ts │ │ ├── commands.ts │ │ ├── document.ts │ │ ├── indent.ts │ │ ├── markdown.test.ts │ │ ├── markdown.test.ts.md │ │ ├── markdown.test.ts.snap │ │ ├── parseMarkdown.ts │ │ └── text-styles.ts │ └── index.ts │ └── tsconfig.json ├── db └── migrations │ └── 101000_alpine_apk_index.sql ├── node.mk ├── package.json ├── packages ├── common │ ├── .prettierignore │ ├── .swcrc │ ├── Makefile │ ├── next-env.d.ts │ ├── package.json │ ├── src │ │ ├── ai │ │ │ └── cv │ │ │ │ ├── index.ts │ │ │ │ └── types.d.ts │ │ ├── aports │ │ │ ├── index.ts │ │ │ ├── upgrade.ts │ │ │ └── utils │ │ │ │ ├── apkbuild.ts │ │ │ │ ├── aports.ts │ │ │ │ ├── git.ts │ │ │ │ └── pkg.ts │ │ ├── bencode │ │ │ ├── Bencode.test.ts │ │ │ ├── Bencode.ts │ │ │ ├── BencodeDecoder.ts │ │ │ ├── BencodeEncoder.ts │ │ │ └── spec.test.ts │ │ ├── components │ │ │ ├── index.ts │ │ │ └── useInit.tsx │ │ ├── gen │ │ │ └── pb │ │ │ │ ├── wener │ │ │ │ └── wode │ │ │ │ │ └── bin │ │ │ │ │ └── v1 │ │ │ │ │ ├── BinStorageService_pb.d.ts │ │ │ │ │ └── BinStorageService_pb.js │ │ │ │ └── wode │ │ │ │ ├── agent │ │ │ │ ├── host │ │ │ │ │ └── v1 │ │ │ │ │ │ ├── NetworkAgentService_pb.d.ts │ │ │ │ │ │ └── NetworkAgentService_pb.js │ │ │ │ └── v1 │ │ │ │ │ ├── AgentService_pb.d.ts │ │ │ │ │ └── AgentService_pb.js │ │ │ │ ├── fs │ │ │ │ └── v1 │ │ │ │ │ ├── FileSystemService_pb.d.ts │ │ │ │ │ └── FileSystemService_pb.js │ │ │ │ ├── resource │ │ │ │ └── v1 │ │ │ │ │ ├── ListQuery_pb.d.ts │ │ │ │ │ ├── ListQuery_pb.js │ │ │ │ │ ├── Resource_pb.d.ts │ │ │ │ │ └── Resource_pb.js │ │ │ │ ├── storage │ │ │ │ └── object │ │ │ │ │ └── v1 │ │ │ │ │ ├── ObjectStorageService_pb.d.ts │ │ │ │ │ └── ObjectStorageService_pb.js │ │ │ │ └── wecom │ │ │ │ └── archive │ │ │ │ └── v1 │ │ │ │ ├── WecomArchiveService_pb.d.ts │ │ │ │ └── WecomArchiveService_pb.js │ │ ├── icons │ │ │ ├── BarcodePrintOutlined.tsx │ │ │ ├── BarcodeReadOutlined.tsx │ │ │ ├── BarcodeScanOutlined.tsx │ │ │ ├── BittorrentFilled.tsx │ │ │ ├── BtFileFilled.tsx │ │ │ ├── CaCertificateOutlined.tsx │ │ │ ├── CertificateVerifiedBadgeOutlined.tsx │ │ │ ├── CertificateVerifiedFilled.tsx │ │ │ ├── DarkModeFilled.tsx │ │ │ ├── DictOutlined.tsx │ │ │ ├── DingtalkBrandIcon.tsx │ │ │ ├── ExternalLinkOutlined.tsx │ │ │ ├── HashLockOutlined.tsx │ │ │ ├── Icons.stories.mdx │ │ │ ├── IpfsOutlined.tsx │ │ │ ├── KongLogo.tsx │ │ │ ├── LightModeFilled.tsx │ │ │ ├── MagnetOutlined.tsx │ │ │ ├── ManTiedOutlined.tsx │ │ │ ├── QqBrandIcon.tsx │ │ │ ├── QrcodePrintOutlined.tsx │ │ │ ├── QrcodeReadOutlined.tsx │ │ │ ├── README.md │ │ │ ├── RtcOutlined.tsx │ │ │ ├── TorrentFileFilled.tsx │ │ │ ├── UTorrentFilled.tsx │ │ │ ├── WebTorrentBrandIcon.tsx │ │ │ ├── WechatBrandIcon.tsx │ │ │ ├── WecomBrandIcon.tsx │ │ │ ├── WecomOutlineIcon.tsx │ │ │ ├── WenerAvatarIcon.tsx │ │ │ ├── WikipediaOutlined.tsx │ │ │ ├── WomenWithMicroPhoneFilled.tsx │ │ │ ├── index.ts │ │ │ └── svg │ │ │ │ ├── brands │ │ │ │ ├── DingtalkBrandIcon.svg │ │ │ │ ├── QQBrandIcon.svg │ │ │ │ ├── WebTorrentBrandIcon.svg │ │ │ │ ├── WechatBrandIcon.svg │ │ │ │ ├── WecomBrandIcon.svg │ │ │ │ └── WenerAvatarIcon.svg │ │ │ │ └── icons │ │ │ │ ├── BarcodePrintOutlined.svg │ │ │ │ ├── BarcodeReadOutlined.svg │ │ │ │ ├── BarcodeScanOutlined.svg │ │ │ │ ├── BittorrentFilled.svg │ │ │ │ ├── BtFileFilled.svg │ │ │ │ ├── CaCertificateOutlined.svg │ │ │ │ ├── CertificateVerifiedBadgeOutlined.svg │ │ │ │ ├── CertificateVerifiedFilled.svg │ │ │ │ ├── DarkModeFilled.svg │ │ │ │ ├── DictOutlined.svg │ │ │ │ ├── ExternalLinkOutlined.svg │ │ │ │ ├── HashLockOutlined.svg │ │ │ │ ├── IpfsOutlined.svg │ │ │ │ ├── KongLogo.svg │ │ │ │ ├── LightModeFilled.svg │ │ │ │ ├── MagnetOutlined.svg │ │ │ │ ├── ManTiedOutlined.svg │ │ │ │ ├── QrcodePrintOutlined.svg │ │ │ │ ├── QrcodeReadOutlined.svg │ │ │ │ ├── RtcOutlined.svg │ │ │ │ ├── TorrentFileFilled.svg │ │ │ │ ├── UTorrentFilled.svg │ │ │ │ ├── WecomOutlineIcon.svg │ │ │ │ ├── WikipediaOutlined.svg │ │ │ │ └── WomenWithMicroPhoneFilled.svg │ │ ├── npm │ │ │ ├── PackageJson.ts │ │ │ ├── RegistryPackage.ts │ │ │ ├── SQLiteStorage.ts │ │ │ ├── Unpkg.ts │ │ │ ├── UnpkgStorage.ts │ │ │ ├── createBearerAuthFetch.ts │ │ │ ├── createUnpkg.ts │ │ │ ├── createUnpkgHandler.ts │ │ │ ├── index.ts │ │ │ ├── mime.test.ts │ │ │ ├── mime.ts │ │ │ ├── server.ts │ │ │ ├── typedoc.ts │ │ │ └── unpkg.test.ts │ │ ├── poc │ │ │ ├── alpine │ │ │ │ ├── README.md │ │ │ │ ├── createGraphSchema.ts │ │ │ │ ├── createHelperRoute.ts │ │ │ │ ├── createTypeGraphSchema.ts │ │ │ │ ├── entity │ │ │ │ │ ├── ApkIndexEntity.ts │ │ │ │ │ └── ApkIndexPkgEntity.ts │ │ │ │ ├── hono.test.ts │ │ │ │ ├── main.ts │ │ │ │ ├── pothos │ │ │ │ │ └── createSchemaBuilder.ts │ │ │ │ ├── repo │ │ │ │ │ ├── RepoClient.test.ts │ │ │ │ │ ├── RepoClient.ts │ │ │ │ │ ├── const.ts │ │ │ │ │ ├── fetchApkIndex.ts │ │ │ │ │ ├── fs.ts │ │ │ │ │ ├── getMirrorStatus.ts │ │ │ │ │ ├── idx.ts │ │ │ │ │ ├── parseApkIndex.ts │ │ │ │ │ ├── parseApkIndexArchive.ts │ │ │ │ │ ├── parsePackageId.test.ts │ │ │ │ │ ├── parsePackageId.ts │ │ │ │ │ ├── toNodeReadableStream.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── server.ts │ │ │ │ └── service │ │ │ │ │ └── ApkIndexService.ts │ │ │ ├── bbvm │ │ │ │ ├── BBVM.ts │ │ │ │ ├── BaseRuntime.ts │ │ │ │ ├── BasicGuiRuntime.ts │ │ │ │ ├── CanvasRuntime.ts │ │ │ │ ├── README.md │ │ │ │ ├── bbasm │ │ │ │ │ ├── Makefile │ │ │ │ │ ├── bbasm.pegjs │ │ │ │ │ ├── bbasm.test.ts │ │ │ │ │ ├── bbasm.ts │ │ │ │ │ ├── format.ts │ │ │ │ │ ├── hexdump.ts │ │ │ │ │ ├── parser.d.ts │ │ │ │ │ ├── parser.js │ │ │ │ │ └── types.ts │ │ │ │ ├── bbvm.main.ts │ │ │ │ ├── format.ts │ │ │ │ ├── inst.test.ts │ │ │ │ ├── lib.ts │ │ │ │ ├── marshalInstruction.ts │ │ │ │ ├── readInstruction.ts │ │ │ │ ├── rlb │ │ │ │ │ ├── index.ts │ │ │ │ │ └── rlb.ts │ │ │ │ ├── rt.ts │ │ │ │ ├── runBbvm.ts │ │ │ │ └── types.ts │ │ │ ├── cli │ │ │ │ ├── createFileCommand.ts │ │ │ │ ├── createGostCommand.ts │ │ │ │ ├── createMacosCommand.ts │ │ │ │ ├── createNetflixCommand.ts │ │ │ │ ├── createWecCommand.ts │ │ │ │ ├── io.ts │ │ │ │ ├── ndev.main.ts │ │ │ │ ├── run.ts │ │ │ │ └── wec.main.ts │ │ │ ├── contracts │ │ │ │ ├── Dao.json │ │ │ │ ├── GeoWeb.json │ │ │ │ ├── Makefile │ │ │ │ ├── Moloch.json │ │ │ │ ├── PartySwap.json │ │ │ │ ├── contracts.json │ │ │ │ └── gen.test.ts │ │ │ ├── domains │ │ │ │ └── README.md │ │ │ ├── fs │ │ │ │ ├── FS.ts │ │ │ │ └── README.md │ │ │ ├── gost │ │ │ │ ├── runGostAutoSwitch.ts │ │ │ │ └── types.ts │ │ │ ├── helm │ │ │ │ └── types.ts │ │ │ ├── ldap │ │ │ │ ├── README.md │ │ │ │ └── types.ts │ │ │ ├── local │ │ │ │ └── getLocalDatabase.ts │ │ │ ├── macos │ │ │ │ └── KeychainAccess.ts │ │ │ ├── netflix │ │ │ │ ├── createFetchWithProxy2.ts │ │ │ │ ├── netflix.test.ts │ │ │ │ ├── runNetflixCheck.ts │ │ │ │ └── verifyNetflixProxy.ts │ │ │ ├── nordvpn │ │ │ │ ├── Client.ts │ │ │ │ ├── README.md │ │ │ │ └── types.ts │ │ │ ├── react-serialize │ │ │ │ ├── poc.test.tsx │ │ │ │ └── serialize.ts │ │ │ └── storage │ │ │ │ ├── AsyncStorage.ts │ │ │ │ ├── README.md │ │ │ │ ├── Storage.ts │ │ │ │ ├── removeNullChar.test.ts │ │ │ │ ├── removeNullChar.ts │ │ │ │ └── serialize.ts │ │ ├── schemas │ │ │ ├── gen.test.ts │ │ │ ├── generateSchema.ts │ │ │ ├── index.ts │ │ │ ├── typebox │ │ │ │ └── wode.ts │ │ │ ├── well-known.ts │ │ │ ├── wode.d.ts │ │ │ └── zod │ │ │ │ └── wode.ts │ │ └── torrent │ │ │ ├── fixtures │ │ │ ├── bitlove-intro.torrent │ │ │ ├── leaves-duplicate-tracker.torrent │ │ │ ├── leaves-empty-announce-list.torrent │ │ │ ├── leaves-empty-url-list.torrent │ │ │ └── leaves-url-list.torrent │ │ │ ├── magnet.ts │ │ │ ├── parseTorrent.test.ts │ │ │ ├── parseTorrent.ts │ │ │ └── torrent.ts │ ├── svgo.config.mjs │ ├── tsconfig.json │ └── vitest.config.ts ├── system │ ├── LICENSE.md │ ├── Makefile │ ├── README.md │ ├── index.ts │ ├── package.json │ ├── rollup.bundle.mjs │ ├── rollup.dev.mjs │ ├── server.ts │ ├── src │ │ ├── hooks │ │ │ ├── hook.test.ts │ │ │ ├── instantiatePackageProtocol.ts │ │ │ └── resolveBareSpecifier.ts │ │ ├── index.ts │ │ ├── loaders │ │ │ ├── hookSystem.ts │ │ │ ├── loadBrowserSystem.ts │ │ │ └── loadServerSystem.ts │ │ ├── server.ts │ │ ├── tests │ │ │ ├── react-remote.test.ts │ │ │ ├── react.test.ts │ │ │ └── system.test.ts │ │ ├── typedoc.ts │ │ └── utils │ │ │ ├── addPreload.ts │ │ │ ├── getGlobalSystem.ts │ │ │ ├── resolve.test.ts │ │ │ └── resolve.ts │ └── tsconfig.json ├── wener-client │ ├── .env │ ├── .gitignore │ ├── .swcrc │ ├── Makefile │ ├── README.md │ ├── lib.d.ts │ ├── libs │ │ └── WeWorkFinanceSdk │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── WeWorkFinanceSdk_C.h │ │ │ ├── libWeWorkFinanceSdk_C.so │ │ │ ├── md5.txt │ │ │ └── version.txt │ ├── package.json │ ├── src │ │ ├── 17dz │ │ │ ├── Client.ts │ │ │ ├── README.md │ │ │ ├── crypto │ │ │ │ ├── crypto.test.ts │ │ │ │ ├── decrypt.ts │ │ │ │ ├── encrypt.ts │ │ │ │ ├── getCryptoKey.ts │ │ │ │ └── index.ts │ │ │ ├── errors.ts │ │ │ ├── flow │ │ │ │ ├── index.ts │ │ │ │ └── login │ │ │ │ │ ├── const.ts │ │ │ │ │ ├── cookieToString.ts │ │ │ │ │ ├── getSession.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── runLoginFlow.ts │ │ │ ├── index.ts │ │ │ ├── operator │ │ │ │ ├── OperatorClient.ts │ │ │ │ ├── getLoginSession.ts │ │ │ │ ├── index.ts │ │ │ │ ├── requestFromSession.ts │ │ │ │ └── types.ts │ │ │ ├── request.ts │ │ │ ├── sign.test.ts │ │ │ ├── sign.ts │ │ │ └── types.ts │ │ ├── ExpiryValue.ts │ │ ├── ValueHolder.ts │ │ ├── ai │ │ │ └── chat │ │ │ │ ├── ChatClient.ts │ │ │ │ └── schema.ts │ │ ├── alicloud │ │ │ ├── AliCloudClient.ts │ │ │ ├── DytnsV20200217.ts │ │ │ ├── OcrV20210707.ts │ │ │ ├── OcrV20210707.types.ts │ │ │ ├── README.md │ │ │ ├── apis.ts │ │ │ ├── index.ts │ │ │ ├── request.ts │ │ │ ├── schema │ │ │ │ ├── gen.test.ts │ │ │ │ └── spec.ts │ │ │ ├── signv3.test.ts │ │ │ └── signv3.ts │ │ ├── baidu │ │ │ └── ce │ │ │ │ ├── getAccessToken.ts │ │ │ │ └── index.ts │ │ ├── browser │ │ │ ├── index.ts │ │ │ └── launch │ │ │ │ ├── connect.ts │ │ │ │ ├── index.ts │ │ │ │ └── launch.ts │ │ ├── browserless │ │ │ └── index.ts │ │ ├── cubejs │ │ │ ├── CubeClient.test.ts │ │ │ ├── CubeClient.ts │ │ │ ├── README.md │ │ │ ├── index.ts │ │ │ ├── service.ts │ │ │ └── types.ts │ │ ├── feishu │ │ │ ├── README.md │ │ │ ├── document │ │ │ │ ├── block │ │ │ │ │ ├── Block.ts │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ └── server │ │ │ │ └── index.ts │ │ ├── funasr │ │ │ ├── index.ts │ │ │ ├── requestOffline.ts │ │ │ └── types.ts │ │ ├── index.ts │ │ ├── openai │ │ │ ├── OpenAiClient.ts │ │ │ ├── OpenAiClientError.ts │ │ │ ├── buildRequest.ts │ │ │ ├── endpoints.ts │ │ │ ├── gen.test.ts │ │ │ ├── index.ts │ │ │ ├── messages.ts │ │ │ ├── request.ts │ │ │ └── types.ts │ │ ├── qq │ │ │ ├── index.ts │ │ │ └── utils │ │ │ │ ├── emotions.json │ │ │ │ ├── parseEmotion.test.ts │ │ │ │ └── parseEmotion.ts │ │ ├── server │ │ │ ├── createFileExpiryValue.ts │ │ │ └── index.ts │ │ ├── utils │ │ │ ├── cookie.ts │ │ │ └── doRequest.ts │ │ ├── wechat │ │ │ ├── README.md │ │ │ ├── WechatErrors.ts │ │ │ ├── WxJsSdk.ts │ │ │ ├── buildUrl.ts │ │ │ ├── createJsSdkSignature.ts │ │ │ ├── getRedirectUri.ts │ │ │ ├── getWxJsSdk.ts │ │ │ ├── index.ts │ │ │ ├── miniprogram │ │ │ │ ├── crypto.test.ts │ │ │ │ ├── crypto.ts │ │ │ │ ├── decryptData.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ │ ├── server │ │ │ │ ├── WechatConfig.ts │ │ │ │ ├── WechatServerClient.ts │ │ │ │ ├── getAccessToken.ts │ │ │ │ ├── index.ts │ │ │ │ ├── request.ts │ │ │ │ └── types.ts │ │ │ ├── utils │ │ │ │ ├── parseMention.test.ts │ │ │ │ ├── parseMention.ts │ │ │ │ ├── parseQuoteMessage.tsx │ │ │ │ └── useragent.ts │ │ │ └── webhook │ │ │ │ ├── PKCS7.ts │ │ │ │ ├── WechatWebhookHandler.ts │ │ │ │ ├── crypt.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ ├── wecom │ │ │ ├── archive │ │ │ │ ├── bun │ │ │ │ │ ├── WeWorkFinanceClient.bun.test.ts │ │ │ │ │ ├── WeWorkFinanceClient.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── enum.ts │ │ │ │ ├── index.ts │ │ │ │ ├── server │ │ │ │ │ ├── decryptRandomKey.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── types.ts │ │ │ │ └── utils │ │ │ │ │ ├── collectSdkFiles.ts │ │ │ │ │ ├── normalizeMessageTypeContent.ts │ │ │ │ │ ├── parseChatRecordMessageItem.ts │ │ │ │ │ ├── parseMixedMessageItem.ts │ │ │ │ │ └── utils.test.ts │ │ │ ├── buildProviderUrl.ts │ │ │ ├── buildUrl.ts │ │ │ ├── getWecomJsSdk.ts │ │ │ ├── index.ts │ │ │ ├── server │ │ │ │ ├── WecomClientError.ts │ │ │ │ ├── WecomConfig.ts │ │ │ │ ├── WecomCorpClient.test.ts │ │ │ │ ├── WecomCorpClient.ts │ │ │ │ ├── api.ts │ │ │ │ ├── index.ts │ │ │ │ ├── parseErrorMessage.test.ts │ │ │ │ ├── parseErrorMessage.ts │ │ │ │ ├── request.ts │ │ │ │ ├── types.ts │ │ │ │ └── webhook.ts │ │ │ ├── useragent.ts │ │ │ └── webhook │ │ │ │ ├── crypto.test.ts │ │ │ │ ├── crypto.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ ├── xunfei │ │ │ ├── index.ts │ │ │ └── spark │ │ │ │ ├── XunfeiConfig.ts │ │ │ │ ├── XunfeiSparkClient.ts │ │ │ │ ├── auth.test.ts │ │ │ │ ├── buildAuthParams.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ └── yzf │ │ │ ├── Client.ts │ │ │ ├── decrypt.ts │ │ │ ├── errors.ts │ │ │ ├── index.ts │ │ │ ├── request.ts │ │ │ ├── token.ts │ │ │ └── types.ts │ ├── tsconfig.json │ └── vitest.config.ts ├── wener-common │ ├── .prettierignore │ ├── .swcrc │ ├── Makefile │ ├── package.json │ ├── src │ │ ├── cn │ │ │ ├── DivisionCode.test.ts │ │ │ ├── DivisionCode.ts │ │ │ ├── Mod11Checksum.ts │ │ │ ├── Mod31Checksum.ts │ │ │ ├── ResidentIdentityCardNumber.test.ts │ │ │ ├── ResidentIdentityCardNumber.ts │ │ │ ├── UnifiedSocialCreditCode.test.ts │ │ │ ├── UnifiedSocialCreditCode.ts │ │ │ ├── __snapshots__ │ │ │ │ ├── ResidentIdentityCardNumber.test.ts.snap │ │ │ │ └── UnifiedSocialCreditCode.test.ts.snap │ │ │ ├── formatDate.ts │ │ │ ├── index.ts │ │ │ ├── parseSex.ts │ │ │ └── types.d.ts │ │ ├── index.ts │ │ ├── jsonschema │ │ │ ├── JsonSchema.test.ts │ │ │ ├── JsonSchema.ts │ │ │ ├── index.ts │ │ │ └── types.d.ts │ │ ├── meta │ │ │ ├── defineFileType.tsx │ │ │ ├── defineInit.ts │ │ │ ├── defineMetadata.test.ts │ │ │ ├── defineMetadata.ts │ │ │ └── index.ts │ │ ├── normalizePagination.ts │ │ ├── parseSort.test.ts │ │ ├── parseSort.ts │ │ ├── password │ │ │ ├── PHC.test.ts │ │ │ ├── PHC.ts │ │ │ ├── Password.test.ts │ │ │ ├── Password.ts │ │ │ ├── createArgon2PasswordAlgorithm.ts │ │ │ ├── createBase64PasswordAlgorithm.ts │ │ │ ├── createBcryptPasswordAlgorithm.ts │ │ │ ├── createPBKDF2PasswordAlgorithm.ts │ │ │ ├── createScryptPasswordAlgorithm.ts │ │ │ ├── index.ts │ │ │ └── server │ │ │ │ └── index.ts │ │ ├── search │ │ │ ├── AdvanceSearch.test.ts │ │ │ ├── AdvanceSearch.ts │ │ │ ├── Makefile │ │ │ ├── __snapshots__ │ │ │ │ └── AdvanceSearch.test.ts.snap │ │ │ ├── formatAdvanceSearch.ts │ │ │ ├── index.ts │ │ │ ├── optimizeAdvanceSearch.ts │ │ │ ├── parseAdvanceSearch.ts │ │ │ ├── parser.d.ts │ │ │ ├── parser.js │ │ │ ├── parser.peggy │ │ │ └── types.d.ts │ │ └── tools │ │ │ └── renderJsonSchemaToMarkdownDoc.ts │ ├── tsconfig.json │ └── vitest.config.ts ├── wener-console │ ├── .prettierignore │ ├── .prettierrc.json │ ├── .storybook │ │ ├── main.ts │ │ └── preview.tsx │ ├── .swcrc │ ├── Makefile │ ├── README.md │ ├── index.html │ ├── lib.d.ts │ ├── next-env.d.ts │ ├── next.config.mjs │ ├── package.json │ ├── postcss.config.cjs │ ├── public │ │ ├── docs.html │ │ ├── graphiql.html │ │ └── robots.txt │ ├── src │ │ ├── assets │ │ │ └── LoginSplash.jpg │ │ ├── buildinfo │ │ │ ├── getBuildInfo.ts │ │ │ └── index.ts │ │ ├── client │ │ │ └── graphql │ │ │ │ ├── getGraphQLUrl.ts │ │ │ │ ├── getUrqlClient.ts │ │ │ │ ├── gqlr.ts │ │ │ │ └── index.ts │ │ ├── components │ │ │ ├── ComponentProvider.tsx │ │ │ ├── ComponentRegistry.stories.tsx │ │ │ ├── DevOnly.tsx │ │ │ ├── ErrorPlaceholder.tsx │ │ │ ├── FunctionButton.tsx │ │ │ ├── HeaderContentFooterLayout.tsx │ │ │ ├── LeftCenterRightLayout.tsx │ │ │ ├── NotReadyPlaceholder.tsx │ │ │ ├── PortalContainer.tsx │ │ │ ├── ViewModeInput.tsx │ │ │ ├── WebVitals.tsx │ │ │ ├── index.ts │ │ │ └── useReportWebVitals.tsx │ │ ├── console │ │ │ ├── AppActor.tsx │ │ │ ├── AppConfLoader.tsx │ │ │ ├── Authenticated.tsx │ │ │ ├── ConsoleLauncher │ │ │ │ ├── ConsoleLauncher.tsx │ │ │ │ ├── Launcher.stories.tsx │ │ │ │ ├── Launcher.tsx │ │ │ │ ├── LauncherStore.tsx │ │ │ │ └── index.ts │ │ │ ├── ConsoleLoader.tsx │ │ │ ├── applets │ │ │ │ ├── Clock │ │ │ │ │ ├── Clock.stories.tsx │ │ │ │ │ └── Clock.tsx │ │ │ │ ├── ClockWidget.tsx │ │ │ │ ├── defineApplet.ts │ │ │ │ └── index.ts │ │ │ ├── components │ │ │ │ ├── ConsoleComponent.tsx │ │ │ │ ├── ConsoleLayout │ │ │ │ │ ├── ConsoleLayout.tsx │ │ │ │ │ ├── ConsoleLayoutContext.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── DockLayout │ │ │ │ │ ├── DockClock.tsx │ │ │ │ │ ├── DockLayout.tsx │ │ │ │ │ ├── DockUserAvatar.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── ModuleMainLayout.tsx │ │ │ │ ├── ReactRouterTracker.tsx │ │ │ │ ├── RootRouterReactor.tsx │ │ │ │ ├── StaticRootReactor.tsx │ │ │ │ └── index.ts │ │ │ ├── context.ts │ │ │ ├── globals.css │ │ │ ├── hooks │ │ │ │ ├── index.ts │ │ │ │ └── useUserPreferenceState.tsx │ │ │ ├── index.ts │ │ │ ├── pages │ │ │ │ ├── AppearanceSettingPage │ │ │ │ │ └── AppearanceSettingPage.tsx │ │ │ │ ├── LoginPage │ │ │ │ │ ├── LoginPage.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── SystemAboutPage │ │ │ │ │ ├── SystemAboutPage.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ └── pages.stories.tsx │ │ │ ├── store │ │ │ │ ├── ConsoleStore.ts │ │ │ │ ├── RouteStore.tsx │ │ │ │ └── UserStore.tsx │ │ │ └── user │ │ │ │ ├── UserAuthExpireOverlay.tsx │ │ │ │ ├── UserLoader.tsx │ │ │ │ ├── UserLockOverlay.tsx │ │ │ │ ├── getUserAction.ts │ │ │ │ └── index.ts │ │ ├── const.ts │ │ ├── daisy │ │ │ ├── Button │ │ │ │ └── Button.tsx │ │ │ ├── Checkbox │ │ │ │ └── Checkbox.tsx │ │ │ ├── Daisy.ts │ │ │ ├── DaisyCollapsible.tsx │ │ │ ├── DaisyDrawer.tsx │ │ │ ├── DaisyDropdownMenu.tsx │ │ │ ├── DaisyTabs.tsx │ │ │ ├── GotoPageInput │ │ │ │ └── GotoPageInput.tsx │ │ │ ├── Input │ │ │ │ └── Input.tsx │ │ │ ├── NonIdealState │ │ │ │ └── NonIdealState.tsx │ │ │ ├── PageSizeSelect │ │ │ │ └── PageSizeSelect.tsx │ │ │ ├── Pagination │ │ │ │ └── Pagination.tsx │ │ │ ├── const.ts │ │ │ ├── index.ts │ │ │ ├── isNodeTypeOf.tsx │ │ │ ├── renderRegion.tsx │ │ │ ├── theme │ │ │ │ ├── DaisyTheme.tsx │ │ │ │ ├── DaisyThemeDemo.tsx │ │ │ │ ├── ThemeListSelector.tsx │ │ │ │ ├── ThemePreviewCard.tsx │ │ │ │ ├── ThemeSelectorButton.tsx │ │ │ │ ├── getSupportedThemes.tsx │ │ │ │ ├── getTheme.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── setElementThemeAttribute.tsx │ │ │ │ ├── theme.stories.tsx │ │ │ │ └── useTheme.tsx │ │ │ └── utils │ │ │ │ └── daisy.ts │ │ ├── floating │ │ │ ├── Drawer.tsx │ │ │ ├── Popover.tsx │ │ │ ├── Tooltip.tsx │ │ │ ├── index.ts │ │ │ ├── useFloatingInteractions.tsx │ │ │ └── usePopover.tsx │ │ ├── foundation │ │ │ ├── auth │ │ │ │ ├── AuthBlock.tsx │ │ │ │ ├── AuthReady.tsx │ │ │ │ ├── AuthStore.ts │ │ │ │ └── index.ts │ │ │ └── site │ │ │ │ ├── SiteLoader.tsx │ │ │ │ ├── SiteSidecar.tsx │ │ │ │ ├── SiteStore.ts │ │ │ │ └── index.ts │ │ ├── hooks │ │ │ ├── index.ts │ │ │ ├── useContextStore.tsx │ │ │ ├── useExposeDebug.ts │ │ │ ├── useLogger.ts │ │ │ └── usePageSizeOptions.tsx │ │ ├── icons │ │ │ ├── ChinaResidentIdentityCardBack.tsx │ │ │ ├── ChinaResidentIdentityCardFront.tsx │ │ │ ├── DingtalkBrandIcon.tsx │ │ │ ├── FinanceIcon.tsx │ │ │ ├── Makefile │ │ │ ├── PinduoduoBrandIcon.tsx │ │ │ ├── QqBrandIcon.tsx │ │ │ ├── TaxIcon.tsx │ │ │ ├── TicketIcon.tsx │ │ │ ├── WechatBrandIcon.tsx │ │ │ ├── WecomBrandIcon.tsx │ │ │ ├── WecomOutlineIcon.tsx │ │ │ ├── index.ts │ │ │ └── svg │ │ │ │ ├── brands │ │ │ │ ├── DingtalkBrandIcon.svg │ │ │ │ ├── PinduoduoBrandIcon.svg │ │ │ │ ├── QQBrandIcon.svg │ │ │ │ ├── WechatBrandIcon.svg │ │ │ │ └── WecomBrandIcon.svg │ │ │ │ ├── color │ │ │ │ ├── ChinaResidentIdentityCardBack.svg │ │ │ │ └── ChinaResidentIdentityCardFront.svg │ │ │ │ └── icons │ │ │ │ ├── FinanceIcon.svg │ │ │ │ ├── TaxIcon.svg │ │ │ │ ├── TicketIcon.svg │ │ │ │ └── WecomOutlineIcon.svg │ │ ├── index.ts │ │ ├── jsonschema │ │ │ ├── createFromJsonSchema.ts │ │ │ └── index.ts │ │ ├── loader │ │ │ ├── AlexWarnesCssLoader.tsx │ │ │ ├── BarsSpinner.tsx │ │ │ ├── BoxShuffle.tsx │ │ │ ├── DotsFadeLoader │ │ │ │ ├── DotsFadeLoader.module.css │ │ │ │ └── DotsFadeLoader.tsx │ │ │ ├── GooeyLoader.tsx │ │ │ ├── LoadingIndicator.tsx │ │ │ ├── README.md │ │ │ ├── index.ts │ │ │ └── loaders.stories.tsx │ │ ├── matomo │ │ │ ├── MatomoTracker.tsx │ │ │ ├── MatomoTrackerStore.ts │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── meta │ │ │ └── index.ts │ │ ├── react-hook-form │ │ │ ├── ReactHookForm.tsx │ │ │ ├── getDirtyFields.tsx │ │ │ ├── getFieldErrors.tsx │ │ │ └── index.ts │ │ ├── router │ │ │ ├── index.ts │ │ │ ├── usePrompt.ts │ │ │ └── useRouteTitles.tsx │ │ ├── serve │ │ │ └── Responses.ts │ │ ├── toast │ │ │ ├── TODO.ts │ │ │ ├── index.ts │ │ │ ├── invariant.ts │ │ │ ├── resolveErrorMessage.ts │ │ │ ├── showErrorToast.tsx │ │ │ ├── showPromiseToast.tsx │ │ │ ├── showSuccessToast.tsx │ │ │ └── warn.ts │ │ ├── tw │ │ │ ├── cn.test.ts │ │ │ ├── cn.ts │ │ │ └── index.ts │ │ ├── types.ts │ │ ├── urql │ │ │ ├── batchFetchExchange.ts │ │ │ ├── createUrqlClient.ts │ │ │ └── index.ts │ │ ├── utils │ │ │ ├── NetworkStatus.tsx │ │ │ ├── UserAgentPreference.tsx │ │ │ ├── getPrefersColorSchema.tsx │ │ │ └── requestIdleCallback.ts │ │ ├── vite-env.d.ts │ │ ├── web │ │ │ ├── ConsoleContext.ts │ │ │ ├── NonIdealPage.tsx │ │ │ ├── PageErrorState.tsx │ │ │ ├── components │ │ │ │ ├── ActiveToggleIcon.tsx │ │ │ │ ├── ErrorSuspenseBoundary │ │ │ │ │ ├── ErrorSuspenseBoundary.tsx │ │ │ │ │ ├── PageErrorState.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── Image.tsx │ │ │ │ ├── ImagePreview │ │ │ │ │ ├── ImagePreview.stories.tsx │ │ │ │ │ ├── ImagePreview.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── LeftContentRightLayout.tsx │ │ │ │ ├── Link.tsx │ │ │ │ ├── OverlayScrollbar.tsx │ │ │ │ ├── TitleTabLayout.tsx │ │ │ │ ├── TitleTabList.tsx │ │ │ │ ├── UpdateNotification │ │ │ │ │ ├── UpdateNotification.tsx │ │ │ │ │ ├── UpdateNotificationToast.tsx │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ ├── formats │ │ │ │ └── EmptyPlaceholder.tsx │ │ │ ├── hooks │ │ │ │ ├── env.tsx │ │ │ │ ├── index.ts │ │ │ │ └── useLocalStorageState.ts │ │ │ ├── index.ts │ │ │ ├── layouts │ │ │ │ ├── DockLayout │ │ │ │ │ ├── DockClock.tsx │ │ │ │ │ ├── DockLayout.tsx │ │ │ │ │ └── DockUserAvatar.tsx │ │ │ │ ├── ExpandableSideMenuLayout │ │ │ │ │ ├── BaseNavLink.tsx │ │ │ │ │ ├── ExpandableSideMenuLayout.module.css │ │ │ │ │ └── ExpandableSideMenuLayout.tsx │ │ │ │ ├── LeftSideMenuBarLayout │ │ │ │ │ ├── LeftSideMenuBarLayout.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── MenuLayout.tsx │ │ │ │ ├── SettingLayout │ │ │ │ │ └── SettingLayout.tsx │ │ │ │ ├── Slot.tsx │ │ │ │ └── index.ts │ │ │ ├── links │ │ │ │ ├── ActiveLink.tsx │ │ │ │ ├── AutoNavLink.tsx │ │ │ │ ├── BaseNavLink.tsx │ │ │ │ ├── NextNavLink.tsx │ │ │ │ ├── StaticNavLink.tsx │ │ │ │ └── index.ts │ │ │ ├── module │ │ │ │ ├── DynamicStore.test.ts │ │ │ │ ├── DynamicStore.ts │ │ │ │ ├── ModuleService.ts │ │ │ │ └── types.ts │ │ │ ├── pages │ │ │ │ └── index.ts │ │ │ ├── prefs.ts │ │ │ ├── resource │ │ │ │ └── index.ts │ │ │ ├── site │ │ │ │ └── SiteLogo.tsx │ │ │ ├── useDebugState.tsx │ │ │ ├── usePageLayoutState.tsx │ │ │ ├── utils │ │ │ │ └── index.ts │ │ │ └── window │ │ │ │ └── index.ts │ │ ├── window │ │ │ ├── ReactWindow.tsx │ │ │ ├── Window.stories.tsx │ │ │ ├── Window.tsx │ │ │ ├── WindowController.tsx │ │ │ ├── WindowFrame.tsx │ │ │ ├── WindowGuest.tsx │ │ │ ├── WindowHost.tsx │ │ │ ├── WindowStyleStore.tsx │ │ │ ├── WindowTest.tsx │ │ │ ├── const.ts │ │ │ ├── index.ts │ │ │ ├── macos │ │ │ │ ├── MacOSWindowController.tsx │ │ │ │ ├── MacOSWindowFrame.tsx │ │ │ │ └── macOS.module.css │ │ │ ├── useWindowTheme.tsx │ │ │ └── windows │ │ │ │ ├── Windows.module.css │ │ │ │ ├── WindowsWindowController.tsx │ │ │ │ └── WindowsWindowFrame.tsx │ │ └── zustand │ │ │ ├── createStoreContext.ts │ │ │ ├── createStoreSelectorHook.ts │ │ │ └── index.ts │ ├── svgo.config.mjs │ ├── tailwind.config.ts │ ├── tsconfig.json │ ├── vite.config.ts │ └── vitest.config.ts ├── wener-miniquery │ ├── .gitognore │ ├── .prettierignore │ ├── .swcrc │ ├── Makefile │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── mikro-orm │ │ │ ├── Makefile │ │ │ ├── index.ts │ │ │ ├── parser.d.ts │ │ │ ├── parser.js │ │ │ ├── parser.pegjs │ │ │ ├── parser.test.ts │ │ │ └── toMikroOrmQuery.ts │ │ └── ohm │ │ │ ├── ast.test.ts │ │ │ ├── ast.ts │ │ │ ├── grammar │ │ │ ├── index.ts │ │ │ ├── miniquery.ohm │ │ │ ├── miniquery.ohm-bundle.d.ts │ │ │ └── miniquery.ohm-bundle.js │ │ │ ├── index.ts │ │ │ ├── miniquery.test.ts │ │ │ └── sequelize │ │ │ ├── __snapshots__ │ │ │ └── where.test.ts.snap │ │ │ ├── index.ts │ │ │ ├── where.test.ts │ │ │ └── where.ts │ └── tsconfig.json ├── wener-nestjs │ ├── .swcrc │ ├── Makefile │ ├── README.md │ ├── package.json │ ├── src │ │ ├── Currents.test.ts │ │ ├── Currents.ts │ │ ├── Errors.ts │ │ ├── Feature.ts │ │ ├── HttpStatus.ts │ │ ├── actuator │ │ │ ├── actuator.module.ts │ │ │ ├── const.ts │ │ │ ├── env.controller.ts │ │ │ ├── health.controller.ts │ │ │ ├── index.ts │ │ │ └── process.controller.ts │ │ ├── app │ │ │ ├── App.test.ts │ │ │ ├── App.ts │ │ │ ├── Contexts.ts │ │ │ └── index.ts │ │ ├── auth │ │ │ ├── AuthPrincipal.ts │ │ │ ├── getRequest.ts │ │ │ ├── index.ts │ │ │ ├── public.decorator.ts │ │ │ ├── role.enum.ts │ │ │ ├── roles.decorator.ts │ │ │ └── roles.guard.ts │ │ ├── config │ │ │ ├── __snapshots__ │ │ │ │ └── config.test.ts.snap │ │ │ ├── config.test.ts │ │ │ ├── database.config.ts │ │ │ ├── index.ts │ │ │ ├── minio.config.ts │ │ │ ├── nats.config.ts │ │ │ ├── redis.config.ts │ │ │ ├── root.config.ts │ │ │ └── server.config.ts │ │ ├── context.ts │ │ ├── createBootstrap.ts │ │ ├── decorator │ │ │ ├── cookies.decorator.ts │ │ │ └── index.ts │ │ ├── entity │ │ │ ├── BaseHttpRequestLogEntity.ts │ │ │ ├── CurrentTenantIdFilter.ts │ │ │ ├── README.md │ │ │ ├── StandardBaseEntity.ts │ │ │ ├── TenantBaseEntity.ts │ │ │ ├── audit │ │ │ │ ├── AuditLogEntity.ts │ │ │ │ ├── AuditModule.ts │ │ │ │ ├── AuditService.ts │ │ │ │ ├── collectAuditData.ts │ │ │ │ ├── enum.ts │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ ├── writeAuditLog.ts │ │ │ │ ├── writeEntityAuditLog.ts │ │ │ │ ├── writeSystemAuditLog.ts │ │ │ │ └── writeUserAuditLog.ts │ │ │ ├── defineEntity.test.ts │ │ │ ├── defineEntity.ts │ │ │ ├── enum.ts │ │ │ ├── env.ts │ │ │ ├── index.ts │ │ │ ├── mixins │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ ├── withAuditorRefEntity.ts │ │ │ │ ├── withCodeEntity.ts │ │ │ │ ├── withCustomerRefEntity.ts │ │ │ │ ├── withDisplayOrderEntity.ts │ │ │ │ ├── withEntityRefEntity.ts │ │ │ │ ├── withHierarchyEntity.ts │ │ │ │ ├── withMetadataEntity.ts │ │ │ │ ├── withNotesEntity.ts │ │ │ │ ├── withOwnerRefEntity.ts │ │ │ │ ├── withRequiredEntityRefEntity.ts │ │ │ │ ├── withSidEntity.ts │ │ │ │ ├── withSlugEntity.ts │ │ │ │ ├── withStateStatusEntity.ts │ │ │ │ ├── withSystemManagedEntity.ts │ │ │ │ ├── withTagsEntity.ts │ │ │ │ ├── withTidEntity.ts │ │ │ │ ├── withTitleDescriptionEntity.ts │ │ │ │ ├── withVendorRefEntity.ts │ │ │ │ └── withVersionEntity.ts │ │ │ ├── parseEntityTypeId.ts │ │ │ ├── patchMikroORMMetadataStorage.ts │ │ │ ├── resolveEntityRef.tsx │ │ │ ├── service │ │ │ │ ├── AutoEntityService.ts │ │ │ │ ├── BaseEntityService.ts │ │ │ │ ├── EntityBaseService.ts │ │ │ │ ├── EntityClass.ts │ │ │ │ ├── EntityService2.ts │ │ │ │ ├── README.md │ │ │ │ ├── applyListQuery.ts │ │ │ │ ├── applyQueryFilter.ts │ │ │ │ ├── applyResolveQuery.ts │ │ │ │ ├── applySearch.ts │ │ │ │ ├── bindEntity.ts │ │ │ │ ├── createQueryBuilder.ts │ │ │ │ ├── findAllEntity.ts │ │ │ │ ├── hasEntityFeature.ts │ │ │ │ ├── index.ts │ │ │ │ ├── normalizePagination.ts │ │ │ │ ├── parseOrder.ts │ │ │ │ ├── resolveEntity.ts │ │ │ │ ├── resolveEntityContext.ts │ │ │ │ ├── resolveSearch.test.ts │ │ │ │ ├── resolveSearch.ts │ │ │ │ ├── services.ts │ │ │ │ ├── toKnexOrder.test.ts │ │ │ │ ├── toKnexOrder.ts │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ │ ├── setCustomerRef.ts │ │ │ ├── setData.ts │ │ │ ├── setEntityRef.ts │ │ │ ├── setOwnerRef.ts │ │ │ └── types.ts │ │ ├── hono │ │ │ ├── createHono.ts │ │ │ ├── createOpenAPIHono.ts │ │ │ ├── createProbeRoute.ts │ │ │ ├── index.ts │ │ │ ├── runServer.ts │ │ │ └── serve.ts │ │ ├── index.ts │ │ ├── ioredis │ │ │ ├── index.ts │ │ │ └── parseRedisOptions.ts │ │ ├── knex │ │ │ ├── index.ts │ │ │ └── parseKnexUri.ts │ │ ├── mikro-orm │ │ │ ├── OrmModule.ts │ │ │ ├── context.ts │ │ │ ├── defineMikroOrmOptions.ts │ │ │ ├── entity │ │ │ │ ├── MinimalBaseEntity.ts │ │ │ │ ├── MinimalEnumBaseEntity.ts │ │ │ │ ├── MinimalResourceBaseEntity.ts │ │ │ │ ├── MinimalTenantBaseEntity.ts │ │ │ │ └── types.ts │ │ │ └── index.ts │ │ ├── modules │ │ │ └── index.ts │ │ ├── nats │ │ │ ├── NatsModule.ts │ │ │ ├── connect.ts │ │ │ ├── index.ts │ │ │ ├── nats.module.test.ts │ │ │ └── service │ │ │ │ ├── NatsServerHandler.ts │ │ │ │ ├── NatsServerRegistry.ts │ │ │ │ ├── NatsServiceClientConnectionModule.ts │ │ │ │ ├── NatsServiceClientModule.ts │ │ │ │ ├── NatsServiceServerModule.ts │ │ │ │ ├── ServerModule.ts │ │ │ │ ├── addNatsService.ts │ │ │ │ ├── createMsgHdrFromResponse.ts │ │ │ │ ├── createNatsClientConnection.ts │ │ │ │ ├── createNatsErrorResponse.ts │ │ │ │ ├── createResponseFromMessageHeader.ts │ │ │ │ ├── handleNatsServiceRequest.ts │ │ │ │ ├── index.ts │ │ │ │ ├── nats-service.test.ts │ │ │ │ ├── nats.ts │ │ │ │ ├── requestNatsService.ts │ │ │ │ └── types.ts │ │ ├── remote │ │ │ ├── README.md │ │ │ ├── RemoteService.ts │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── scripts │ │ │ ├── bundle.esbuild.ts │ │ │ └── esbuild │ │ │ │ ├── bundle.ts │ │ │ │ ├── createDynamicImportPlugin.ts │ │ │ │ ├── createExcludeVendorSourceMapPlugin.ts │ │ │ │ ├── createTscPlugin.ts │ │ │ │ └── index.ts │ │ ├── service │ │ │ ├── client │ │ │ │ ├── ClientRegistry.ts │ │ │ │ ├── RemoteMethodNotImplemented.ts │ │ │ │ ├── RemoteServiceOf.ts │ │ │ │ ├── ServiceClientModule.ts │ │ │ │ ├── createProxyClient.ts │ │ │ │ ├── createRemoteServiceClient.ts │ │ │ │ ├── handleResponse.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ │ ├── index.ts │ │ │ ├── meta │ │ │ │ ├── Method.ts │ │ │ │ ├── Service.ts │ │ │ │ ├── client.types.ts │ │ │ │ ├── doc-gen.test.ts │ │ │ │ ├── getServerServiceSchema.ts │ │ │ │ ├── getServiceSchema.test.ts │ │ │ │ ├── getServiceSchema.ts │ │ │ │ ├── index.ts │ │ │ │ └── server.types.ts │ │ │ ├── schema.ts │ │ │ ├── server │ │ │ │ ├── ServiceRegistry.ts │ │ │ │ ├── ServiceServerModule.ts │ │ │ │ ├── createResponseFromRequest.ts │ │ │ │ ├── createServerContextMiddleware.ts │ │ │ │ ├── createServerLoggingMiddleware.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ │ ├── service.test.ts │ │ │ ├── types.ts │ │ │ ├── utils.test.ts │ │ │ ├── utils.ts │ │ │ └── wks │ │ │ │ ├── InstanceService.ts │ │ │ │ ├── MetaService.ts │ │ │ │ └── index.ts │ │ ├── type-graphql │ │ │ ├── BaseNode.ts │ │ │ ├── BaseObject.ts │ │ │ ├── FileScalar.ts │ │ │ ├── GeneralRequestInput.ts │ │ │ ├── GeneralResponseResolver.ts │ │ │ ├── GraphQLJSONScalar.ts │ │ │ ├── JSONArgs.ts │ │ │ ├── NestContainerType.ts │ │ │ ├── README.md │ │ │ ├── buildGraphModule.ts │ │ │ ├── entity │ │ │ │ ├── index.ts │ │ │ │ └── resolveNodeType.ts │ │ │ ├── getObjectName.ts │ │ │ ├── getTypeCache.ts │ │ │ ├── graph.test.ts │ │ │ ├── index.ts │ │ │ ├── interface │ │ │ │ ├── HasAuditorRefNode.ts │ │ │ │ ├── HasCodeNode.ts │ │ │ │ ├── HasDisplayOrderNode.ts │ │ │ │ ├── HasEntityRefNode.ts │ │ │ │ ├── HasMetadataNode.ts │ │ │ │ ├── HasNotesNode.ts │ │ │ │ ├── HasOwnerRefNode.ts │ │ │ │ ├── HasSlugNode.ts │ │ │ │ ├── HasStateStatusNode.ts │ │ │ │ ├── HasTagsNode.ts │ │ │ │ ├── HasTitleDescriptionNode.ts │ │ │ │ └── index.ts │ │ │ ├── mixins │ │ │ │ ├── const.ts │ │ │ │ ├── createDataType.ts │ │ │ │ ├── index.ts │ │ │ │ ├── withCodeType.ts │ │ │ │ ├── withDisplayOrderType.ts │ │ │ │ ├── withMetadataType.ts │ │ │ │ ├── withNotesType.ts │ │ │ │ └── withTagsType.ts │ │ │ ├── relay.ts │ │ │ ├── resolveGraphQLJSON.ts │ │ │ ├── resolver │ │ │ │ ├── HasMetadataResolver.ts │ │ │ │ ├── HasTagsResolver.ts │ │ │ │ └── index.ts │ │ │ ├── resource │ │ │ │ ├── ListQueryInput.ts │ │ │ │ ├── OnConflictInput.ts │ │ │ │ ├── ResField.ts │ │ │ │ ├── args.ts │ │ │ │ ├── createBaseEntityResolver.ts │ │ │ │ ├── createListPayload.ts │ │ │ │ ├── factory.ts │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ └── withBaseQuery.ts │ │ │ ├── runRelayClientMutation.ts │ │ │ └── types.ts │ │ ├── types.ts │ │ ├── util │ │ │ ├── getStaticRootPath.ts │ │ │ ├── loadEnvs.ts │ │ │ └── requireFound.ts │ │ └── yoga │ │ │ └── index.ts │ └── tsconfig.json ├── wener-reaction │ ├── Makefile │ ├── README.md │ ├── package.json │ ├── rollup.bundle.mjs │ ├── rollup.dev.mjs │ ├── src │ │ ├── components │ │ │ ├── ClientOnly.tsx │ │ │ ├── DevOnly.tsx │ │ │ ├── ErrorBoundary.tsx │ │ │ ├── ErrorSuspenseBoundary.tsx │ │ │ ├── MountedOnly.tsx │ │ │ ├── ProdOnly.tsx │ │ │ ├── ReactShadowRoot.tsx │ │ │ └── ServerOnly.tsx │ │ ├── hoc │ │ │ ├── hoistNonReactStatics.ts │ │ │ └── withDefaultProps.ts │ │ ├── hooks │ │ │ ├── useAbortController.ts │ │ │ ├── useAsyncEffect.ts │ │ │ ├── useCompareEffect.ts │ │ │ ├── useConstant.ts │ │ │ ├── useContainer.tsx │ │ │ ├── useControllable.ts │ │ │ ├── useDebounce.ts │ │ │ ├── useDebugRender.tsx │ │ │ ├── useDeepCompareHooks.ts │ │ │ ├── useDeepEqual.tsx │ │ │ ├── useDomEventListener.ts │ │ │ ├── useEffectOnce.ts │ │ │ ├── useEvent.ts │ │ │ ├── useEventListener.ts │ │ │ ├── useForceRender.ts │ │ │ ├── useInterval.ts │ │ │ ├── useIsoMorphicEffect.ts │ │ │ ├── useLatestValue.ts │ │ │ ├── useMediaQuery.ts │ │ │ ├── useMounted.ts │ │ │ ├── usePageVisibility.ts │ │ │ ├── usePrevious.ts │ │ │ ├── usePromise.tsx │ │ │ ├── useRenderCount.ts │ │ │ └── useTimeout.tsx │ │ ├── index.ts │ │ ├── mutative │ │ │ └── zustand │ │ │ │ └── index.ts │ │ ├── next │ │ │ ├── NextNavLink.tsx │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── render │ │ │ ├── FlexRenderer.tsx │ │ │ ├── flexRender.tsx │ │ │ ├── isReactComponent.tsx │ │ │ ├── renderAlternative.tsx │ │ │ ├── renderReactNode.test.tsx │ │ │ ├── renderReactNodeToMarkdown.tsx │ │ │ └── renderReactNodeToText.tsx │ │ ├── router │ │ │ ├── index.ts │ │ │ ├── lazyRoute.ts │ │ │ └── useRouteTitles.tsx │ │ ├── store │ │ │ ├── NetworkStatus.tsx │ │ │ └── index.ts │ │ ├── typing.ts │ │ ├── universal.ts │ │ ├── utils │ │ │ ├── createDeepCompareHooks.tsx │ │ │ ├── createReactContext.ts │ │ │ ├── mergeProps.tsx │ │ │ └── mergeRefs.tsx │ │ └── valtio │ │ │ ├── index.ts │ │ │ ├── proxyWith.ts │ │ │ ├── proxyWithCompare.test.ts │ │ │ └── proxyWithCompare.tsx │ ├── tsconfig.json │ ├── typedoc.json │ └── types.d.ts └── wener-utils │ ├── .prettierignore │ ├── .swcrc │ ├── LICENSE.md │ ├── Makefile │ ├── README.md │ ├── package.json │ ├── rollup.bundle.mjs │ ├── rollup.dev.mjs │ ├── src │ ├── arrays │ │ ├── MaybeArray.ts │ │ └── arrayFromAsync.ts │ ├── asyncs │ │ ├── AsyncInterval.ts │ │ ├── MaybePromise.ts │ │ ├── Promises.ts │ │ ├── createAsyncIterator.ts │ │ ├── createLazyPromise.test.ts │ │ ├── createLazyPromise.ts │ │ ├── firstOfAsyncIterator.ts │ │ ├── generatorOfStream.ts │ │ ├── isIterator.ts │ │ ├── isPromise.ts │ │ ├── isThenable.ts │ │ ├── nextOfAsyncIterator.ts │ │ ├── promiseOfCallback.ts │ │ └── timeout.ts │ ├── browsers │ │ ├── copy.ts │ │ ├── download.ts │ │ ├── getFileFromDataTransfer.ts │ │ └── loaders.ts │ ├── cn │ │ ├── README.md │ │ ├── division │ │ │ ├── DivisionCode.ts │ │ │ ├── binarySearch.test.ts │ │ │ ├── binarySearch.ts │ │ │ └── division.test.ts │ │ ├── formatChineseAmount.ts │ │ ├── id │ │ │ ├── Mod11.ts │ │ │ ├── ResidentIdNumber.ts │ │ │ └── id.test.ts │ │ ├── index.ts │ │ ├── parseChineseNumber.test.ts │ │ ├── parseChineseNumber.ts │ │ ├── pinyin │ │ │ ├── cartesianProduct.test.ts │ │ │ ├── cartesianProduct.ts │ │ │ ├── data.json │ │ │ ├── loader.ts │ │ │ ├── preload.ts │ │ │ ├── toPinyin.test.ts │ │ │ ├── toPinyinPure.ts │ │ │ └── transform.ts │ │ ├── scripts │ │ │ └── gen.test.ts │ │ ├── types.ts │ │ └── uscc │ │ │ ├── Mod31.ts │ │ │ ├── USCC.ts │ │ │ ├── isUSCC.ts │ │ │ └── uscc.test.ts │ ├── crypto │ │ ├── base.ts │ │ ├── getNodeCrypto.ts │ │ ├── hashing.test.ts │ │ ├── hashing.ts │ │ ├── md5.bench.ts │ │ ├── md5.d.ts │ │ ├── md5.js │ │ ├── md5.test.ts │ │ ├── pem │ │ │ ├── __snapshots__ │ │ │ │ └── pem.test.ts.snap │ │ │ ├── pem.test.ts │ │ │ └── pem.ts │ │ ├── ulid.test.ts │ │ └── ulid.ts │ ├── emitter │ │ └── types.ts │ ├── errors │ │ ├── Errors.test.ts │ │ └── Errors.ts │ ├── fetch │ │ ├── HttpStatus.ts │ │ ├── createFetchWith.ts │ │ ├── createFetchWithLogging.ts │ │ ├── createFetchWithRetry.ts │ │ ├── dumpRequest.ts │ │ ├── dumpResponse.ts │ │ ├── index.ts │ │ └── types.ts │ ├── i18n │ │ ├── createTranslate.test.ts │ │ └── createTranslate.ts │ ├── index.ts │ ├── io │ │ ├── AbstractEncoding.ts │ │ ├── ArrayBuffer.test-d.ts │ │ ├── ArrayBuffers.base64.test.ts │ │ ├── ArrayBuffers.test.ts │ │ ├── ArrayBuffers.ts │ │ ├── Buffer.test.ts │ │ ├── Buffer.ts │ │ ├── ByteBuffer.test.ts │ │ ├── ByteBuffer.ts │ │ ├── base64.ts │ │ ├── dump.ts │ │ ├── isBuffer.test.ts │ │ ├── isBuffer.ts │ │ ├── isTransferable.test.ts │ │ ├── isTransferable.ts │ │ ├── parseDataUri.test.ts │ │ └── parseDataUri.ts │ ├── langs │ │ ├── AsyncCloser.ts │ │ ├── Closer.ts │ │ ├── MaybeFunction.ts │ │ ├── README.md │ │ ├── classOf.ts │ │ ├── deepEqual.test.ts │ │ ├── deepEqual.ts │ │ ├── deepFreeze.ts │ │ ├── getGlobalStates.ts │ │ ├── getObjectId.ts │ │ ├── ifPresent.ts │ │ ├── isClass.ts │ │ ├── isDefined.ts │ │ ├── isEmptyObject.ts │ │ ├── isFunction.ts │ │ ├── isNullish.ts │ │ ├── isPlainObject.ts │ │ ├── langs.test.ts │ │ ├── memoize.ts │ │ ├── mixin.test.ts │ │ ├── mixin.ts │ │ ├── parseBoolean.ts │ │ ├── shallowClone.ts │ │ └── shallowEqual.ts │ ├── libs │ │ ├── README.md │ │ ├── ms.test.ts │ │ └── ms.ts │ ├── logging │ │ ├── Logger.ts │ │ ├── createChildLogger.ts │ │ ├── createLogger.ts │ │ ├── createNoopLogger.ts │ │ ├── logger.test.ts │ │ ├── slog.test.ts │ │ └── slog.ts │ ├── maths │ │ ├── clamp.test.ts │ │ ├── clamp.ts │ │ ├── createRandom.test.ts │ │ └── random.ts │ ├── mitt │ │ ├── README.md │ │ └── index.ts │ ├── modules │ │ ├── isModule.ts │ │ ├── parseModuleId.test.ts │ │ └── parseModuleId.ts │ ├── objects │ │ ├── computeIfAbsent.ts │ │ ├── get.test-d.ts │ │ ├── get.ts │ │ ├── merge │ │ │ ├── index.ts │ │ │ ├── isMergeableObject.ts │ │ │ ├── merge.test.ts │ │ │ └── merge.ts │ │ ├── parseObjectPath.test.ts │ │ ├── parseObjectPath.ts │ │ ├── set.test.ts │ │ └── set.ts │ ├── schema │ │ └── typebox │ │ │ ├── index.ts │ │ │ └── typebox.ts │ ├── scripts │ │ └── getGenerateContext.ts │ ├── server │ │ ├── crypto │ │ │ └── md5.ts │ │ ├── fetch │ │ │ ├── createFetchWithProxy.ts │ │ │ ├── createFetchWithProxyByNodeFetch.ts │ │ │ └── createFetchWithProxyByUndici.ts │ │ ├── getPackageDir.ts │ │ ├── index.ts │ │ ├── jsdom.ts │ │ ├── node-fetch.ts │ │ ├── polyfill │ │ │ ├── polyfillBrowser.test.ts │ │ │ ├── polyfillBrowser.ts │ │ │ ├── polyfillCrypto.ts │ │ │ ├── polyfillFetch.ts │ │ │ ├── polyfillJsDom.ts │ │ │ └── polyfillWebSocket.ts │ │ └── ws.ts │ ├── strings │ │ ├── camelCase.ts │ │ ├── formatBytes.ts │ │ ├── renderTemplate.test.ts │ │ └── renderTemplate.ts │ ├── typedoc.ts │ ├── types.d.ts │ ├── validations │ │ ├── asserts.ts │ │ ├── isUUID.test.ts │ │ ├── isUUID.ts │ │ ├── parseTimestamp.test.ts │ │ └── parseTimestamp.ts │ └── web │ │ ├── getGlobalThis.ts │ │ ├── getRandomValues.ts │ │ ├── randomUUID.ts │ │ ├── requestIdleCallback.ts │ │ ├── structuredClone.test.ts │ │ └── structuredClone.ts │ ├── tsconfig.json │ ├── typedoc.json │ └── vitest.config.ts ├── patches └── ts-node@11.0.0-beta.1.patch ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── postcss.config.cjs ├── protos ├── bundles │ ├── google │ │ ├── api │ │ │ ├── README.md │ │ │ ├── annotations.proto │ │ │ ├── auth.proto │ │ │ ├── backend.proto │ │ │ ├── billing.proto │ │ │ ├── client.proto │ │ │ ├── config_change.proto │ │ │ ├── consumer.proto │ │ │ ├── context.proto │ │ │ ├── control.proto │ │ │ ├── distribution.proto │ │ │ ├── documentation.proto │ │ │ ├── endpoint.proto │ │ │ ├── field_behavior.proto │ │ │ ├── http.proto │ │ │ ├── httpbody.proto │ │ │ ├── label.proto │ │ │ ├── launch_stage.proto │ │ │ ├── log.proto │ │ │ ├── logging.proto │ │ │ ├── metric.proto │ │ │ ├── monitored_resource.proto │ │ │ ├── monitoring.proto │ │ │ ├── quota.proto │ │ │ ├── resource.proto │ │ │ ├── routing.proto │ │ │ ├── service.proto │ │ │ ├── source_info.proto │ │ │ ├── system_parameter.proto │ │ │ └── usage.proto │ │ ├── protobuf │ │ │ ├── any.proto │ │ │ ├── api.proto │ │ │ ├── cpp_features.proto │ │ │ ├── descriptor.proto │ │ │ ├── duration.proto │ │ │ ├── empty.proto │ │ │ ├── field_mask.proto │ │ │ ├── late_loaded_option.proto │ │ │ ├── late_loaded_option_user.proto │ │ │ ├── sample_messages_edition.proto │ │ │ ├── source_context.proto │ │ │ ├── struct.proto │ │ │ ├── timestamp.proto │ │ │ ├── type.proto │ │ │ └── wrappers.proto │ │ ├── rpc │ │ │ ├── README.md │ │ │ ├── code.proto │ │ │ ├── context │ │ │ │ └── attribute_context.proto │ │ │ ├── error_details.proto │ │ │ └── status.proto │ │ └── type │ │ │ ├── README.md │ │ │ ├── calendar_period.proto │ │ │ ├── color.proto │ │ │ ├── date.proto │ │ │ ├── datetime.proto │ │ │ ├── dayofweek.proto │ │ │ ├── expr.proto │ │ │ ├── fraction.proto │ │ │ ├── latlng.proto │ │ │ ├── money.proto │ │ │ ├── month.proto │ │ │ ├── postal_address.proto │ │ │ ├── quaternion.proto │ │ │ └── timeofday.proto │ └── validate │ │ └── validate.proto └── wode │ ├── wener │ └── wode │ │ └── bin │ │ └── v1 │ │ └── BinStorageService.proto │ └── wode │ ├── agent │ ├── host │ │ └── v1 │ │ │ └── NetworkAgentService.proto │ └── v1 │ │ └── AgentService.proto │ ├── fs │ └── v1 │ │ └── FileSystemService.proto │ ├── resource │ ├── dynamic │ │ └── v1 │ │ │ └── DynamicResourceService.proto │ ├── protos.proto │ └── v1 │ │ └── ResourceService.proto │ ├── storage │ └── object │ │ └── v1 │ │ └── ObjectStorageService.proto │ └── wecom │ └── archive │ └── v1 │ └── WecomArchiveService.proto ├── rollup.mjs ├── server.mk ├── tailwind.config.ts ├── tsconfig.json └── turbo.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_size = 2 5 | indent_style = space 6 | insert_final_newline = true 7 | charset = utf-8 8 | 9 | [*.svg] 10 | insert_final_newline = false 11 | 12 | [{Makefile,*.mk,justfile}] 13 | indent_style = tab 14 | indent_size = 4 15 | -------------------------------------------------------------------------------- /apps/console/.env: -------------------------------------------------------------------------------- 1 | PORT=3052 2 | 3 | WEB_API_SERVER_PORT=3051 4 | GRAPHQL_URL='http://localhost:3051/graphql' 5 | -------------------------------------------------------------------------------- /apps/console/.gitignore: -------------------------------------------------------------------------------- 1 | public/libs 2 | public/version.json 3 | -------------------------------------------------------------------------------- /apps/console/.prettierignore: -------------------------------------------------------------------------------- 1 | .next 2 | build 3 | dist 4 | node_modules 5 | ignored 6 | -------------------------------------------------------------------------------- /apps/console/graphql.config.yml: -------------------------------------------------------------------------------- 1 | schema: graphql.schema.json 2 | documents: 'src/**/*.graphql' 3 | -------------------------------------------------------------------------------- /apps/console/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | 'postcss-import': {}, 4 | 'tailwindcss/nesting': {}, 5 | tailwindcss: {}, 6 | autoprefixer: {}, 7 | ...(process.env.NODE_ENV === 'production' ? { cssnano: {} } : {}), 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /apps/console/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/apps/console/public/favicon.ico -------------------------------------------------------------------------------- /apps/console/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /api 3 | -------------------------------------------------------------------------------- /apps/console/src/assets/LoginSplash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/apps/console/src/assets/LoginSplash.jpg -------------------------------------------------------------------------------- /apps/console/src/assets/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | { 4 | "name": "LoginSplash.jpg", 5 | "ref": "mel-ghW_jLS8eAw-unsplash.jpg", 6 | "author": { 7 | "url": "https://unsplash.com/@melindapack" 8 | } 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /apps/console/src/casl/index.ts: -------------------------------------------------------------------------------- 1 | export { useAbility, Can, type CanProps, Ability } from './Can'; 2 | export { getUserAbility, can, cannot } from './getUserAbility'; 3 | export type { ConsoleAbility } from './casl'; 4 | -------------------------------------------------------------------------------- /apps/console/src/components/ProdOnly.tsx: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import type { ReactNode } from 'react'; 3 | import { useIsProd } from '@/hooks/env'; 4 | 5 | export const ProdOnly: React.FC<{ children?: ReactNode; fallback?: ReactNode }> = ({ children, fallback = null }) => { 6 | return useIsProd() ? <>{children} : fallback; 7 | }; 8 | -------------------------------------------------------------------------------- /apps/console/src/components/WebVitals.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useReportWebVitals } from './useReportWebVitals'; 4 | 5 | export function WebVitals() { 6 | useReportWebVitals((metric) => { 7 | console.log(metric); 8 | }); 9 | return null; 10 | } 11 | -------------------------------------------------------------------------------- /apps/console/src/components/props.d.ts: -------------------------------------------------------------------------------- 1 | export type ValueProps = { 2 | value?: T; 3 | onValueChange?: (value: T) => void; 4 | defaultValue?: T; 5 | }; 6 | -------------------------------------------------------------------------------- /apps/console/src/components/useReportWebVitals.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { onCLS, onFCP, onFID, onINP, onLCP, onTTFB, type Metric } from 'web-vitals'; 3 | 4 | export function useReportWebVitals(reportWebVitalsFn: (metric: Metric) => void) { 5 | useEffect(() => { 6 | onCLS(reportWebVitalsFn); 7 | onFID(reportWebVitalsFn); 8 | onLCP(reportWebVitalsFn); 9 | onINP(reportWebVitalsFn); 10 | onFCP(reportWebVitalsFn); 11 | onTTFB(reportWebVitalsFn); 12 | }, [reportWebVitalsFn]); 13 | } 14 | -------------------------------------------------------------------------------- /apps/console/src/console/components/ConsoleLayout/index.ts: -------------------------------------------------------------------------------- 1 | export { ConsoleLayout } from './ConsoleLayout'; 2 | -------------------------------------------------------------------------------- /apps/console/src/console/components/DockLayout/index.ts: -------------------------------------------------------------------------------- 1 | export { DockLayout } from './DockLayout'; 2 | -------------------------------------------------------------------------------- /apps/console/src/console/createWorkRoutes.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { RouteObject } from 'react-router-dom'; 3 | 4 | export function createWorkRoutes(): RouteObject[] { 5 | return [ 6 | { 7 | path: '/work', 8 | element:
Not ready
, 9 | }, 10 | ]; 11 | } 12 | -------------------------------------------------------------------------------- /apps/console/src/console/loadModule.tsx: -------------------------------------------------------------------------------- 1 | import { isDev } from '@wener/console'; 2 | import type { DynamicModule } from '@wener/console/web'; 3 | 4 | export function loadModule(name: string): Promise { 5 | // vite 没问题 6 | let dyn = (name: string) => import(`./modules/${name}/module.tsx`); 7 | return dyn(name) 8 | .then((v) => { 9 | if (isDev()) { 10 | console.log(`Loaded module ${name}`, v.default); 11 | } 12 | return v; 13 | }) 14 | .then((v) => v.default); 15 | } 16 | -------------------------------------------------------------------------------- /apps/console/src/console/modules/site.core/module.tsx: -------------------------------------------------------------------------------- 1 | import type { DynamicModule } from '@wener/console/web'; 2 | 3 | export default { 4 | onModuleInit: (ctx) => {}, 5 | } satisfies DynamicModule; 6 | -------------------------------------------------------------------------------- /apps/console/src/console/pages/HomePage.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const HomePage = () => { 4 | return
Hello
; 5 | }; 6 | -------------------------------------------------------------------------------- /apps/console/src/console/pages/UserProfilePage.tsx: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import type { ReactNode } from 'react'; 3 | 4 | export const UserProfilePage: React.FC<{ children?: ReactNode }> = () => { 5 | return
UserProfilePage
; 6 | }; 7 | -------------------------------------------------------------------------------- /apps/console/src/console/pages/UserSettingProfile.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const UserSettingProfile = () => { 4 | return
UserSettingProfile
; 5 | }; 6 | -------------------------------------------------------------------------------- /apps/console/src/console/routes/home.route.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { RouteObject } from 'react-router-dom'; 3 | import { HomePage } from '../pages/HomePage'; 4 | 5 | export default { 6 | element: , 7 | } as RouteObject; 8 | -------------------------------------------------------------------------------- /apps/console/src/console/routes/setting.appearance.route.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { RouteObject } from 'react-router-dom'; 3 | import { AppearanceSettingPage } from '@wener/console/pages'; 4 | 5 | export default { 6 | element: , 7 | handle: { 8 | title: '显示设置', 9 | }, 10 | } as RouteObject; 11 | -------------------------------------------------------------------------------- /apps/console/src/console/routes/setting.dev.debug.route.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { RouteObject } from 'react-router-dom'; 3 | import { DevDebugPage } from '@/console/pages/DevDebugPage'; 4 | 5 | export default { 6 | element: , 7 | handle: { 8 | title: '开发设置', 9 | }, 10 | } satisfies RouteObject; 11 | -------------------------------------------------------------------------------- /apps/console/src/console/routes/setting.profile.route.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { RouteObject } from 'react-router-dom'; 3 | import { UserSettingProfile } from '../pages/UserSettingProfile'; 4 | 5 | export default { 6 | element: , 7 | } satisfies RouteObject; 8 | -------------------------------------------------------------------------------- /apps/console/src/console/routes/setting.route.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Outlet, type RouteObject } from 'react-router-dom'; 3 | import { ErrorSuspenseBoundary } from '@wener/reaction'; 4 | import SettingPage from '../pages/SettingPage'; 5 | 6 | export default { 7 | element: ( 8 | 9 | 10 | 11 | 12 | 13 | ), 14 | } as RouteObject; 15 | -------------------------------------------------------------------------------- /apps/console/src/console/routes/setting.system.route.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { RouteObject } from 'react-router-dom'; 3 | import { SystemAboutPage } from '@wener/console/pages'; 4 | 5 | export default { 6 | element: , 7 | handle: { 8 | title: '关于', 9 | }, 10 | } satisfies RouteObject; 11 | -------------------------------------------------------------------------------- /apps/console/src/console/routes/user.$userId.route.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Outlet, type RouteObject } from 'react-router-dom'; 3 | import { ErrorSuspenseBoundary } from '@wener/reaction'; 4 | import { UserProfilePage } from '../pages/UserProfilePage'; 5 | 6 | export default { 7 | element: ( 8 | 9 | 10 | 11 | 12 | 13 | ), 14 | } satisfies RouteObject; 15 | -------------------------------------------------------------------------------- /apps/console/src/foundation/Site/SiteActions.ts: -------------------------------------------------------------------------------- 1 | import { gqlr } from '@wener/console/client/graphql'; 2 | import { PingQuery, ResolveSiteConfMutation } from './query'; 3 | 4 | export namespace SiteActions { 5 | export const ping = async () => { 6 | await gqlr(PingQuery); 7 | return {}; 8 | }; 9 | 10 | export const resolveSiteConf = async (input: { tid?: string }) => { 11 | const { data } = await gqlr(ResolveSiteConfMutation, { input }); 12 | return data.data; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /apps/console/src/foundation/User/UserActions.ts: -------------------------------------------------------------------------------- 1 | import { getUrqlClient } from '@wener/console/client/graphql'; 2 | import { getFragmentData } from '@/gql'; 3 | import { CurrentUserFragment, CurrentUserQuery } from './query'; 4 | 5 | export namespace UserActions { 6 | export async function getCurrentUser() { 7 | const { data, error } = await getUrqlClient().query(CurrentUserQuery, {}); 8 | if (error) { 9 | throw error; 10 | } 11 | return getFragmentData(CurrentUserFragment, data?.data!); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /apps/console/src/gql/index.ts: -------------------------------------------------------------------------------- 1 | export * from './fragment-masking'; 2 | export * from './gql'; 3 | -------------------------------------------------------------------------------- /apps/console/src/hooks/env.tsx: -------------------------------------------------------------------------------- 1 | export function useIsDev() { 2 | return process.env.NODE_ENV === 'development'; 3 | } 4 | 5 | export function useIsProd() { 6 | return !useIsDev(); 7 | } 8 | 9 | export function useIsClient() { 10 | return typeof window !== 'undefined' && typeof location !== 'undefined'; 11 | } 12 | 13 | let _isNextJS: boolean | undefined; 14 | 15 | export function useIsNextJS() { 16 | return (_isNextJS ||= Boolean((globalThis as any).next?.version)); 17 | } 18 | -------------------------------------------------------------------------------- /apps/console/src/instance/index.ts: -------------------------------------------------------------------------------- 1 | export { Instance } from './Instance'; 2 | -------------------------------------------------------------------------------- /apps/console/src/resource/defineResourceModule.tsx: -------------------------------------------------------------------------------- 1 | import type { ResourceSchemaDef } from '@/resource/defineResource'; 2 | 3 | type DefineResourceModuleOptions = { 4 | name: string; 5 | title: string; 6 | resources: ResourceSchemaDef[]; 7 | metadata?: Record; 8 | }; 9 | 10 | /** 11 | * @experimental 12 | */ 13 | export function defineResourceModule(opts: DefineResourceModuleOptions) { 14 | return opts; 15 | } 16 | -------------------------------------------------------------------------------- /apps/console/src/resource/index.ts: -------------------------------------------------------------------------------- 1 | export type { AnyResource } from './types/AnyResource'; 2 | export type { Identifiable } from './types/Identifiable'; 3 | 4 | export { 5 | defineResource, 6 | getResourceSchemas, 7 | isResource, 8 | resolveResourceSchema, 9 | type DefineResourceOptions, 10 | type ResourceSchemaDef, 11 | type ResolveResourceSchemaOptions, 12 | } from './defineResource'; 13 | -------------------------------------------------------------------------------- /apps/console/src/resource/types/Identifiable.ts: -------------------------------------------------------------------------------- 1 | export type Identifiable = { 2 | id: string; 3 | }; 4 | -------------------------------------------------------------------------------- /apps/console/src/resource/utils/getTitleOfResource.tsx: -------------------------------------------------------------------------------- 1 | export function getTitleOfResource(res?: any) { 2 | if (res && typeof res === 'object') { 3 | return res.displayName || res.title || res.fullName || res.loginName || res.topic; 4 | } 5 | return undefined; 6 | } 7 | -------------------------------------------------------------------------------- /apps/console/src/scripts/write-version.ts: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs/promises'; 2 | import { getBuildInfo } from '@wener/console/buildinfo'; 3 | 4 | const info = getBuildInfo(); 5 | console.log(info); 6 | await fs.writeFile('public/version.json', JSON.stringify(info, null, 2)); 7 | -------------------------------------------------------------------------------- /apps/console/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /apps/console/svgo.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | { 4 | "name": "removeAttrs", 5 | "params": { 6 | "attrs": [ 7 | "data-.*" 8 | ] 9 | } 10 | }, 11 | { 12 | "name": "sortAttrs" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /apps/file-server/README.md: -------------------------------------------------------------------------------- 1 | # File Server Browse 2 | 3 | - Static file server 4 | - alternative for https://caddyserver.com/docs/caddyfile/directives/file_server#browse 5 | -------------------------------------------------------------------------------- /apps/file-server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "file-server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "type": "module" 13 | } 14 | -------------------------------------------------------------------------------- /apps/server/.env: -------------------------------------------------------------------------------- 1 | # for Alpine, GitHub 2 | # FETCH_PROXY= 3 | # DATABASE_DSN= 4 | -------------------------------------------------------------------------------- /apps/server/Makefile: -------------------------------------------------------------------------------- 1 | REPO_ROOT ?= $(shell git rev-parse --show-toplevel) 2 | -include $(REPO_ROOT)/server.mk 3 | -------------------------------------------------------------------------------- /apps/server/builds/apis-open-server/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !package.json 4 | -------------------------------------------------------------------------------- /apps/server/builds/apis-open-server/rootfs/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "dependencies": { 6 | "class-transformer": "*", 7 | "jsdom": "^22" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /apps/server/builds/apis-open-server/rootfs/root/.npmrc: -------------------------------------------------------------------------------- 1 | strict-peer-dependencies=true 2 | auto-install-peers=true 3 | legacy-peer-deps=false 4 | sharp_binary_host="https://npmmirror.com/mirrors/sharp" 5 | sharp_libvips_binary_host="https://npmmirror.com/mirrors/sharp-libvips" 6 | -------------------------------------------------------------------------------- /apps/server/builds/openai-proxy/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !package.json 4 | -------------------------------------------------------------------------------- /apps/server/builds/openai-proxy/rootfs/app/.npmrc: -------------------------------------------------------------------------------- 1 | strict-peer-dependencies=true 2 | auto-install-peers=true 3 | legacy-peer-deps=false 4 | sharp_binary_host="https://npmmirror.com/mirrors/sharp" 5 | sharp_libvips_binary_host="https://npmmirror.com/mirrors/sharp-libvips" 6 | -------------------------------------------------------------------------------- /apps/server/builds/openai-proxy/rootfs/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "dependencies": { 6 | "class-transformer": "*", 7 | "sharp": "*" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /apps/server/builds/openai-proxy/rootfs/root/.npmrc: -------------------------------------------------------------------------------- 1 | strict-peer-dependencies=true 2 | auto-install-peers=true 3 | legacy-peer-deps=false 4 | sharp_binary_host="https://npmmirror.com/mirrors/sharp" 5 | sharp_libvips_binary_host="https://npmmirror.com/mirrors/sharp-libvips" 6 | -------------------------------------------------------------------------------- /apps/server/builds/wener-get-server/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !package.json 4 | -------------------------------------------------------------------------------- /apps/server/builds/wener-get-server/rootfs/app/.npmrc: -------------------------------------------------------------------------------- 1 | strict-peer-dependencies=true 2 | auto-install-peers=true 3 | legacy-peer-deps=false 4 | sharp_binary_host="https://npmmirror.com/mirrors/sharp" 5 | sharp_libvips_binary_host="https://npmmirror.com/mirrors/sharp-libvips" 6 | -------------------------------------------------------------------------------- /apps/server/builds/wener-get-server/rootfs/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "dependencies": { 6 | "class-transformer": "*", 7 | "sharp": "*", 8 | "jsdom": "^22" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /apps/server/builds/wener-get-server/rootfs/root/.npmrc: -------------------------------------------------------------------------------- 1 | strict-peer-dependencies=true 2 | auto-install-peers=true 3 | legacy-peer-deps=false 4 | sharp_binary_host="https://npmmirror.com/mirrors/sharp" 5 | sharp_libvips_binary_host="https://npmmirror.com/mirrors/sharp-libvips" 6 | -------------------------------------------------------------------------------- /apps/server/docs/reference/index.html.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Wener APIs 3 | language_tabs: 4 | - javascript: JavaScript 5 | - shell: Shell 6 | - http: HTTP 7 | language_clients: 8 | - javascript: "" 9 | - shell: "" 10 | - http: "" 11 | toc_footers: [] 12 | includes: 13 | - apis-open-server 14 | - errors 15 | search: true 16 | highlight_theme: darkula 17 | headingLevel: 2 18 | 19 | --- 20 | -------------------------------------------------------------------------------- /apps/server/docs/widdershins/templates/openapi3/authentication.def: -------------------------------------------------------------------------------- 1 | 5 | 6 | -------------------------------------------------------------------------------- /apps/server/docs/widdershins/templates/openapi3/authentication_none.def: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /apps/server/docs/widdershins/templates/openapi3/code_http.dot: -------------------------------------------------------------------------------- 1 | {{=data.methodUpper}} {{=data.url}}{{=data.requiredQueryString}} HTTP/1.1 2 | {{? data.host}}Host: {{=data.host}}{{?}} 3 | {{?data.consumes.length}}Content-Type: {{=data.consumes[0]}} 4 | {{?}}{{?data.produces.length}}Accept: {{=data.produces[0]}}{{?}} 5 | {{?data.headerParameters.length}}{{~ data.headerParameters :p:index}}{{=p.name}}: {{=p.exampleValues.object}} 6 | {{~}} 7 | {{?}} 8 | -------------------------------------------------------------------------------- /apps/server/docs/widdershins/templates/openapi3/code_shell.dot: -------------------------------------------------------------------------------- 1 | # 也可以用 wget 2 | curl -X {{=data.methodUpper}} {{=data.url}}{{=data.requiredQueryString}}{{?data.allHeaders.length}} \{{?}} 3 | {{~data.allHeaders :p:index}} -H '{{=p.name}}: {{=p.exampleValues.object}}'{{?index < data.allHeaders.length-1}} \{{?}} 4 | {{~}} 5 | -------------------------------------------------------------------------------- /apps/server/docs/widdershins/templates/openapi3/debug.def: -------------------------------------------------------------------------------- 1 | {{= data.utils.inspect(data) }} 2 | -------------------------------------------------------------------------------- /apps/server/docs/widdershins/templates/openapi3/footer.def: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /apps/server/lib.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | https://github.com/total-typescript/ts-reset/blob/main/src/entrypoints/filter-boolean.d.ts 3 | 4 | https://github.com/microsoft/TypeScript/issues/16655 5 | */ 6 | 7 | interface Array { 8 | filter(predicate: BooleanConstructor, thisArg?: any): NonFalsy[]; 9 | } 10 | 11 | interface ReadonlyArray { 12 | filter(predicate: BooleanConstructor, thisArg?: any): NonFalsy[]; 13 | } 14 | 15 | type NonFalsy = T extends false | 0 | '' | null | undefined | 0n ? never : T; 16 | -------------------------------------------------------------------------------- /apps/server/package.mk: -------------------------------------------------------------------------------- 1 | 2 | run\:%: 3 | @echo "Running $*" 4 | @make SERVER=$(*) run 5 | 6 | dev\:%: 7 | @echo "Dev $*" 8 | @make SERVER=$(*) dev 9 | -------------------------------------------------------------------------------- /apps/server/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: / 3 | -------------------------------------------------------------------------------- /apps/server/src/app/actuator/const.ts: -------------------------------------------------------------------------------- 1 | export function hideActuatorApi() { 2 | return !process.env.ACTUATOR_API; 3 | } 4 | -------------------------------------------------------------------------------- /apps/server/src/app/auth/AuthPrincipal.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 用户、服务账户或机器人 3 | */ 4 | export interface AuthPrincipal { 5 | roles: string[]; 6 | 7 | [key: string]: any; 8 | } 9 | -------------------------------------------------------------------------------- /apps/server/src/app/auth/auth.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { APP_GUARD } from '@nestjs/core'; 3 | import { AuthGuard } from './auth.guard'; 4 | import { RolesGuard } from './roles.guard'; 5 | 6 | @Module({ 7 | providers: [ 8 | { 9 | provide: APP_GUARD, 10 | useClass: AuthGuard, 11 | }, 12 | { 13 | provide: APP_GUARD, 14 | useClass: RolesGuard, 15 | }, 16 | ], 17 | }) 18 | export class AuthModule {} 19 | -------------------------------------------------------------------------------- /apps/server/src/app/auth/check-policies.decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from '@nestjs/common'; 2 | 3 | export const CHECK_POLICIES_KEY = 'check_policy'; 4 | export const CheckPolicies = (...handlers: PolicyHandler[]) => SetMetadata(CHECK_POLICIES_KEY, handlers); 5 | 6 | interface IPolicyHandler { 7 | handle(ability: AuthAbility): boolean; 8 | } 9 | 10 | type PolicyHandlerCallback = (ability: AuthAbility) => boolean; 11 | export type PolicyHandler = IPolicyHandler | PolicyHandlerCallback; 12 | 13 | export interface AuthAbility {} 14 | -------------------------------------------------------------------------------- /apps/server/src/app/auth/index.ts: -------------------------------------------------------------------------------- 1 | export { Role } from './role.enum'; 2 | export { Roles } from './roles.decorator'; 3 | export { CheckPolicies, type PolicyHandler, type AuthAbility } from './check-policies.decorator'; 4 | export { type AuthPrincipal } from './AuthPrincipal'; 5 | export { Public } from './public.decorator'; 6 | -------------------------------------------------------------------------------- /apps/server/src/app/auth/public.decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from '@nestjs/common'; 2 | 3 | export const AUTH_PUBLIC_KEY = 'auth.public'; 4 | export const Public = () => SetMetadata(AUTH_PUBLIC_KEY, true); 5 | -------------------------------------------------------------------------------- /apps/server/src/app/auth/role.enum.ts: -------------------------------------------------------------------------------- 1 | export enum Role { 2 | User = 'user', 3 | Admin = 'admin', 4 | SystemAdmin = 'system-admin', 5 | } 6 | -------------------------------------------------------------------------------- /apps/server/src/app/auth/roles.decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from '@nestjs/common'; 2 | import type { Role } from './role.enum'; 3 | 4 | export const AUTH_ROLES_KEY = 'auth.roles'; 5 | export const Roles = (...roles: Role[]) => SetMetadata(AUTH_ROLES_KEY, roles); 6 | -------------------------------------------------------------------------------- /apps/server/src/app/config/index.ts: -------------------------------------------------------------------------------- 1 | export { RedisConfig } from './redis.config'; 2 | export { ServerConfig } from './server.config'; 3 | export { DatabaseConfig } from './database.config'; 4 | export { RootConfig } from './root.config'; 5 | -------------------------------------------------------------------------------- /apps/server/src/app/config/root.config.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { DatabaseConfig } from './database.config'; 3 | import { RedisConfig } from './redis.config'; 4 | import { ServerConfig } from './server.config'; 5 | 6 | export const RootConfig = z.object({ 7 | server: ServerConfig, 8 | database: DatabaseConfig, 9 | redis: RedisConfig, 10 | }); 11 | export type RootConfig = z.infer; 12 | -------------------------------------------------------------------------------- /apps/server/src/app/decorator/cookies.decorator.ts: -------------------------------------------------------------------------------- 1 | import { createParamDecorator, type ExecutionContext } from '@nestjs/common'; 2 | 3 | export const Cookies = createParamDecorator((data: string, ctx: ExecutionContext) => { 4 | const request = ctx.switchToHttp().getRequest(); 5 | return data ? request.cookies?.[data] : request.cookies; 6 | }); 7 | -------------------------------------------------------------------------------- /apps/server/src/app/decorator/index.ts: -------------------------------------------------------------------------------- 1 | export { Cookies } from './cookies.decorator'; 2 | -------------------------------------------------------------------------------- /apps/server/src/app/graphql/index.ts: -------------------------------------------------------------------------------- 1 | export { GraphQLCoreModule } from './GraphQLCoreModule'; 2 | -------------------------------------------------------------------------------- /apps/server/src/app/index.ts: -------------------------------------------------------------------------------- 1 | export { InjectToken } from './InjectToken'; 2 | export { setAppContext, getContext, getAppContext } from './app.context'; 3 | export * from './hook.module'; 4 | -------------------------------------------------------------------------------- /apps/server/src/app/mikro-orm/entity/EnumBaseEntity.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntity, Entity, PrimaryKey, Property, types } from '@mikro-orm/core'; 2 | 3 | @Entity({ abstract: true }) 4 | export class EnumBaseEntity> extends BaseEntity { 5 | @PrimaryKey({ type: types.string, columnType: 'text' }) 6 | value!: string; 7 | 8 | @Property({ type: types.string, columnType: 'text', nullable: true }) 9 | label?: string; 10 | } 11 | -------------------------------------------------------------------------------- /apps/server/src/app/mikro-orm/entity/index.ts: -------------------------------------------------------------------------------- 1 | export { MinimalBaseEntity, type MinimalOptionalEntityFields } from './MinimalBaseEntity'; 2 | export { EnumBaseEntity } from './EnumBaseEntity'; 3 | -------------------------------------------------------------------------------- /apps/server/src/app/mikro-orm/index.ts: -------------------------------------------------------------------------------- 1 | export * from './context'; 2 | export { MikroOrmErrorFilter } from './mikro-orm.filter'; 3 | -------------------------------------------------------------------------------- /apps/server/src/app/run/index.ts: -------------------------------------------------------------------------------- 1 | export { runApplication, type ApplicationOptions } from '../app.run'; 2 | export { CoreModule, type CoreModuleOptions } from '../core.module'; 3 | -------------------------------------------------------------------------------- /apps/server/src/app/server.module.ts: -------------------------------------------------------------------------------- 1 | import { Module, type MiddlewareConsumer, type NestModule } from '@nestjs/common'; 2 | import { ServerMiddleware } from './middleware/server-middleware.service'; 3 | 4 | @Module({}) 5 | export class ServerModule implements NestModule { 6 | configure(consumer: MiddlewareConsumer): void { 7 | consumer.apply(ServerMiddleware).forRoutes('*'); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /apps/server/src/app/types.ts: -------------------------------------------------------------------------------- 1 | import type { FastifyReply, FastifyRequest } from 'fastify'; 2 | 3 | export type NestRequest = FastifyRequest['raw']; 4 | export type NestResponse = FastifyReply['raw']; 5 | 6 | // https://www.fastify.io/docs/latest/Reference/Middleware/ 7 | export interface NestMiddleware { 8 | use(req: NestRequest, res: NestResponse, next: (error?: Error | any) => void): any; 9 | } 10 | -------------------------------------------------------------------------------- /apps/server/src/apps/wode-api-server/main.ts: -------------------------------------------------------------------------------- 1 | import { loadEnvs } from '@wener/nestjs'; 2 | import { App } from '@wener/nestjs/app'; 3 | import { patchMikroORMMetadataStorage } from '@wener/nestjs/entity'; 4 | 5 | patchMikroORMMetadataStorage(); 6 | process.env.APP_NAME = 'wode'; 7 | process.env.APP_COMPONENT = 'api-server'; 8 | await loadEnvs({ name: App.service }); 9 | const { runDemoApiServer: runServer } = await import('./runServer'); 10 | await runServer(); 11 | -------------------------------------------------------------------------------- /apps/server/src/apps/wode-service-agent/main.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import { loadEnvs } from '@wener/nestjs'; 3 | import { App } from '@wener/nestjs/app'; 4 | import { patchMikroORMMetadataStorage } from '@wener/nestjs/entity'; 5 | 6 | patchMikroORMMetadataStorage(); 7 | 8 | process.env.APP_NAME = 'wode'; 9 | process.env.APP_COMPONENT = 'service-agent'; 10 | 11 | await loadEnvs({ name: App.service }); 12 | const { runServiceAgent: runServer } = await import('./runServiceAgent'); 13 | await runServer(); 14 | -------------------------------------------------------------------------------- /apps/server/src/entity/AccessTokenEntity.ts: -------------------------------------------------------------------------------- 1 | export { AccessTokenEntity } from '../foundation/Auth/entity/AccessTokenEntity'; 2 | -------------------------------------------------------------------------------- /apps/server/src/entity/HttpRequestLogEntity.ts: -------------------------------------------------------------------------------- 1 | import { Entity } from '@mikro-orm/core'; 2 | import { BaseHttpRequestLogEntity } from '../modules/FetchCache'; 3 | 4 | @Entity({ tableName: 'http_request_log' }) 5 | export class HttpRequestLogEntity extends BaseHttpRequestLogEntity {} 6 | -------------------------------------------------------------------------------- /apps/server/src/entity/base/SystemBaseEntity.ts: -------------------------------------------------------------------------------- 1 | import { Entity } from '@mikro-orm/core'; 2 | import { TenantBaseEntity } from '@wener/nestjs/entity'; 3 | 4 | @Entity({ abstract: true }) 5 | export abstract class SystemBaseEntity extends TenantBaseEntity {} 6 | -------------------------------------------------------------------------------- /apps/server/src/entity/base/xtypes.ts: -------------------------------------------------------------------------------- 1 | import { IntegerType } from '@mikro-orm/core'; 2 | 3 | /** 4 | * sql integer as number instead of string 5 | */ 6 | export class IntType extends IntegerType { 7 | convertToJSValue(value: number | undefined): number | undefined { 8 | if (typeof value === 'string') { 9 | return Number.parseInt(value, 10); 10 | } 11 | 12 | return value; 13 | } 14 | } 15 | 16 | export const xtypes = { 17 | int: IntType, 18 | }; 19 | -------------------------------------------------------------------------------- /apps/server/src/foundation/Audit/AuditModule.ts: -------------------------------------------------------------------------------- 1 | import { MikroOrmModule } from '@mikro-orm/nestjs'; 2 | import { Module } from '@nestjs/common'; 3 | import { AuditLogEntity } from './AuditLogEntity'; 4 | import { AuditService } from './AuditService'; 5 | 6 | @Module({ 7 | imports: [MikroOrmModule.forFeature(AuditModule.Entities)], 8 | providers: [AuditService], 9 | exports: [AuditService], 10 | }) 11 | export class AuditModule { 12 | static Entities = [AuditLogEntity]; 13 | } 14 | -------------------------------------------------------------------------------- /apps/server/src/foundation/Audit/AuditService.ts: -------------------------------------------------------------------------------- 1 | import { MikroORM } from '@mikro-orm/postgresql'; 2 | import { Inject, Injectable } from '@nestjs/common'; 3 | 4 | @Injectable() 5 | export class AuditService { 6 | constructor(@Inject(MikroORM) protected readonly orm: MikroORM) {} 7 | } 8 | -------------------------------------------------------------------------------- /apps/server/src/foundation/Audit/index.ts: -------------------------------------------------------------------------------- 1 | export { AuditService } from './AuditService'; 2 | export { collectAuditData } from './collectAuditData'; 3 | export { writeAuditLog } from './writeAuditLog'; 4 | export { writeUserAuditLog } from './writeUserAuditLog'; 5 | export { writeEntityAuditLog, writeEntityChangelog } from './writeEntityAuditLog'; 6 | export { writeSystemAuditLog } from './writeSystemAuditLog'; 7 | export { SystemAuditAction, EntityAuditAction, UserAuditAction } from './enum'; 8 | export type * from './types'; 9 | -------------------------------------------------------------------------------- /apps/server/src/foundation/Auth/entity/index.ts: -------------------------------------------------------------------------------- 1 | export { AuthEntityPermissionEntity } from './AuthEntityPermissionEntity'; 2 | export { AuthEntityRoleEntity } from './AuthEntityRoleEntity'; 3 | export { AuthPermissionEntity } from './AuthPermissionEntity'; 4 | export { AuthRoleEntity } from './AuthRoleEntity'; 5 | export { AccessTokenEntity } from './AccessTokenEntity'; 6 | export { withRolesEntity } from './withRolesEntity'; 7 | -------------------------------------------------------------------------------- /apps/server/src/foundation/ResourceOwner/OwnerNode.ts: -------------------------------------------------------------------------------- 1 | import { BaseNode, RelayNode } from '@wener/nestjs/type-graphql'; 2 | import { InterfaceType } from 'type-graphql'; 3 | 4 | @InterfaceType('OwnerNode', { 5 | autoRegisterImplementations: false, 6 | implements: [BaseNode], 7 | resolveType: (...args) => { 8 | return RelayNode.resolveType(...args); 9 | }, 10 | }) 11 | export class OwnerNode extends BaseNode {} 12 | -------------------------------------------------------------------------------- /apps/server/src/foundation/Tenant/entity/TenantEntity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Property, types, type Opt } from '@mikro-orm/core'; 2 | import { MinimalBaseEntity } from '@wener/nestjs/mikro-orm'; 3 | 4 | @Entity({ tableName: 'tenant', schema: 'public' }) 5 | export class TenantEntity extends MinimalBaseEntity { 6 | @Property({ type: types.string }) 7 | tid!: string & Opt; 8 | 9 | @Property({ type: types.string }) 10 | displayName!: string; 11 | 12 | @Property({ type: types.string }) 13 | fullName!: string; 14 | } 15 | -------------------------------------------------------------------------------- /apps/server/src/foundation/Tenant/index.ts: -------------------------------------------------------------------------------- 1 | export { TenantService } from './TenantService'; 2 | export * from './const'; 3 | -------------------------------------------------------------------------------- /apps/server/src/foundation/entity/ContactMethodType.ts: -------------------------------------------------------------------------------- 1 | import { Entity } from '@mikro-orm/core'; 2 | import { BaseTenantDictEntity } from '@/entity/BaseTenantDictEntity'; 3 | 4 | @Entity({ tableName: 'contact_method_type' }) 5 | export class ContactMethodType extends BaseTenantDictEntity {} 6 | -------------------------------------------------------------------------------- /apps/server/src/foundation/entity/GenderTypeEntity.ts: -------------------------------------------------------------------------------- 1 | import { Entity } from '@mikro-orm/core'; 2 | import { BaseTenantDictEntity } from '@/entity/BaseTenantDictEntity'; 3 | 4 | @Entity({ tableName: 'gender_type' }) 5 | export class GenderTypeEntity extends BaseTenantDictEntity {} 6 | -------------------------------------------------------------------------------- /apps/server/src/foundation/entity/LicenseTypeEntity.ts: -------------------------------------------------------------------------------- 1 | import { Entity } from '@mikro-orm/core'; 2 | import { BaseTenantDictEntity } from '@/entity/BaseTenantDictEntity'; 3 | 4 | @Entity({ tableName: 'license_type' }) 5 | export class LicenseTypeEntity extends BaseTenantDictEntity {} 6 | -------------------------------------------------------------------------------- /apps/server/src/graph/HasRoleObject.ts: -------------------------------------------------------------------------------- 1 | import { RelayNode } from '@wener/nestjs/type-graphql'; 2 | import { InterfaceType } from 'type-graphql'; 3 | 4 | @InterfaceType('HasRole', { 5 | autoRegisterImplementations: false, 6 | implements: [RelayNode], 7 | resolveType: (...args) => { 8 | return RelayNode.resolveType(...args); 9 | }, 10 | }) 11 | export class HasRoleObject extends RelayNode {} 12 | -------------------------------------------------------------------------------- /apps/server/src/graph/TenantBaseObject.ts: -------------------------------------------------------------------------------- 1 | import { BaseNode, BaseObject, RelayNode } from '@wener/nestjs/type-graphql'; 2 | import { ObjectType } from 'type-graphql'; 3 | 4 | @ObjectType({ implements: [RelayNode, BaseNode] }) 5 | export class TenantBaseObject extends BaseObject { 6 | // 不需要这个字段 7 | // @Field(() => String) 8 | // tid!: string; 9 | } 10 | -------------------------------------------------------------------------------- /apps/server/src/graph/const.ts: -------------------------------------------------------------------------------- 1 | export enum SystemRole { 2 | User = 'user', 3 | Employee = 'employee', 4 | Admin = 'admin', 5 | SystemAdmin = 'system:admin', 6 | // Superuser = 'Superuser', 7 | // AppUser = 'AppUser', 8 | Public = 'Public', 9 | } 10 | -------------------------------------------------------------------------------- /apps/server/src/graph/getPubSub.ts: -------------------------------------------------------------------------------- 1 | import type { GeneralResponseObject } from '@wener/nestjs/type-graphql'; 2 | import { createPubSub } from 'graphql-yoga'; 3 | 4 | const pubSub = createPubSub<{ 5 | TICKER: [GeneralResponseObject]; 6 | USER: [string, IMessage]; 7 | }>(); 8 | 9 | export function getPubSub() { 10 | return pubSub; 11 | } 12 | 13 | export type GraphPubSub = typeof pubSub; 14 | 15 | interface IMessage { 16 | type: string; 17 | payload?: any; 18 | metadata?: any; 19 | } 20 | -------------------------------------------------------------------------------- /apps/server/src/modules/FetchCache/HttpRequestLog.ts: -------------------------------------------------------------------------------- 1 | import { Entity } from '@mikro-orm/core'; 2 | import { BaseHttpRequestLogEntity } from './BaseHttpRequestLogEntity'; 3 | 4 | @Entity({ tableName: 'http_request_log' }) 5 | export class HttpRequestLogEntity extends BaseHttpRequestLogEntity {} 6 | -------------------------------------------------------------------------------- /apps/server/src/modules/FetchCache/index.ts: -------------------------------------------------------------------------------- 1 | export { BaseHttpRequestLogEntity } from './BaseHttpRequestLogEntity'; 2 | export { findHttpRequestCache, type FindCacheOptions } from './findHttpRequestCache'; 3 | export { createFetchWithCache, type CreateFetchWithCacheOptions } from './createFetchWithCache'; 4 | -------------------------------------------------------------------------------- /apps/server/src/modules/FetchCache/removeNullChar.ts: -------------------------------------------------------------------------------- 1 | export function removeNullChar(o: any): any { 2 | if (typeof o === 'string') { 3 | return o.replaceAll('\u0000', ''); 4 | } 5 | if (typeof o !== 'object' || !o) { 6 | return o; 7 | } 8 | if (Array.isArray(o)) { 9 | return o.map(removeNullChar); 10 | } 11 | for (const k in o) { 12 | o[k] = removeNullChar(o[k]); 13 | } 14 | return o; 15 | } 16 | -------------------------------------------------------------------------------- /apps/server/src/modules/common/dto/index.ts: -------------------------------------------------------------------------------- 1 | export * from './GeneralResponse.dto'; 2 | export * from './FindQuery'; 3 | export * from './FindResult'; 4 | -------------------------------------------------------------------------------- /apps/server/src/modules/fetch-cache/const.ts: -------------------------------------------------------------------------------- 1 | export const KeyOfFetchCacheModuleOptions = Symbol('FetchCacheModuleOptions'); 2 | -------------------------------------------------------------------------------- /apps/server/src/modules/fetch-cache/index.ts: -------------------------------------------------------------------------------- 1 | export { type FetchCacheHookContext, FetchCache, type FetchCacheConfig } from './FetchCache'; 2 | export { createFetchWithCache, type CreateFetchWithCacheOptions } from './createFetchWithCache'; 3 | export { FetchCacheModule, type FetchCacheModuleOptions } from './fetch-cache.module'; 4 | export { HttpRequestLog } from './HttpRequestLog'; 5 | export { HttpRequestLogRepository } from './HttpRequestLog.repository'; 6 | export { FetchCacheService } from './fetch-cache.service'; 7 | -------------------------------------------------------------------------------- /apps/server/src/modules/fetch-cache/removeNullChar.ts: -------------------------------------------------------------------------------- 1 | export function removeNullChar(o: any): any { 2 | if (typeof o === 'string') { 3 | return o.replaceAll('\u0000', ''); 4 | } 5 | if (typeof o !== 'object' || !o) { 6 | return o; 7 | } 8 | if (Array.isArray(o)) { 9 | return o.map(removeNullChar); 10 | } 11 | for (const k in o) { 12 | o[k] = removeNullChar(o[k]); 13 | } 14 | return o; 15 | } 16 | -------------------------------------------------------------------------------- /apps/server/src/scripts/bundle.esbuild.ts: -------------------------------------------------------------------------------- 1 | import { bundle } from '@wener/nestjs/scripts/esbuild'; 2 | 3 | const SERVER = process.env.SERVER; 4 | if (!SERVER) { 5 | throw new Error(`No server to bundle`); 6 | } 7 | 8 | await Promise.all( 9 | SERVER.split(',') 10 | .map((v) => v.trim()) 11 | .map((v) => 12 | bundle(v, (o) => { 13 | o.external ||= []; 14 | o.external.push( 15 | // 16 | 'mariadb/callback', 17 | ); 18 | }), 19 | ), 20 | ); 21 | -------------------------------------------------------------------------------- /apps/server/src/server/events/index.ts: -------------------------------------------------------------------------------- 1 | export { getEvents } from './events'; 2 | export { getRemoteEvents } from './getRemoteEvents'; 3 | -------------------------------------------------------------------------------- /apps/server/src/server/hono/withHonoContext.ts: -------------------------------------------------------------------------------- 1 | import type { MiddlewareHandler } from 'hono'; 2 | import { runContext } from '@/server/utils/runContext'; 3 | 4 | export function withHonoContext(): MiddlewareHandler { 5 | return async (_, next) => { 6 | return runContext(next); 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /apps/server/src/server/redis/parseRedisOptions.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from 'vitest'; 2 | import { parseRedisOptions } from '@/server/redis/parseRedisOptions'; 3 | 4 | test('parseRedisOptions', () => { 5 | expect(parseRedisOptions('redis://redis/1')).toMatchObject({ 6 | host: 'redis', 7 | port: 6379, 8 | db: 1, 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /apps/server/src/server/redis/redis.ts: -------------------------------------------------------------------------------- 1 | import { Redis } from 'ioredis'; 2 | import { parseRedisOptions } from './parseRedisOptions'; 3 | 4 | export function createRedis() { 5 | let opts = parseRedisOptions({ 6 | url: process.env.REDIS_URL, 7 | username: process.env.REDIS_USERNAME, 8 | password: process.env.REDIS_PASSWORD, 9 | }); 10 | return new Redis({ 11 | maxRetriesPerRequest: null, 12 | ...opts, 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /apps/server/src/util/requireDefined.ts: -------------------------------------------------------------------------------- 1 | export function requireDefined(v: T | undefined | null, message?: string): T { 2 | if (v === undefined || v === null) { 3 | throw new Error(message || 'requireDefined'); 4 | } 5 | return v; 6 | } 7 | -------------------------------------------------------------------------------- /apps/server/src/util/requireResponseOk.ts: -------------------------------------------------------------------------------- 1 | export function requireResponseOk(res: Response) { 2 | if (!res.ok) { 3 | throw new Error(`unexpected response ${res.status} ${res.statusText}`, { cause: res }); 4 | } 5 | return res; 6 | } 7 | -------------------------------------------------------------------------------- /apps/server/src/utils/orm/patchMikroORMMetadataStorage.polyfill.ts: -------------------------------------------------------------------------------- 1 | import { patchMikroORMMetadataStorage } from '@wener/nestjs/entity'; 2 | 3 | patchMikroORMMetadataStorage(); 4 | -------------------------------------------------------------------------------- /apps/web/.env: -------------------------------------------------------------------------------- 1 | GRAPHQL_URL='http://localhost:3051/graphql' 2 | SERVER_URL='http://localhost:3051' 3 | GRAPHQL_TOKEN= 4 | -------------------------------------------------------------------------------- /apps/web/.env.production: -------------------------------------------------------------------------------- 1 | GRAPHQL_URL=http://wode-api-server:3000/graphql 2 | SERVER_URL=http://wode-api-server:3000 3 | -------------------------------------------------------------------------------- /apps/web/.prettierignore: -------------------------------------------------------------------------------- 1 | src/locales 2 | -------------------------------------------------------------------------------- /apps/web/graphql.config.yml: -------------------------------------------------------------------------------- 1 | schema: graphql.schema.json 2 | documents: 'src/**/*.graphql' 3 | -------------------------------------------------------------------------------- /apps/web/lingui.config.ts: -------------------------------------------------------------------------------- 1 | /** @type {import('@lingui/conf').LinguiConfig} */ 2 | import { type LinguiConfig } from '@lingui/conf'; 3 | 4 | const conf: LinguiConfig = { 5 | locales: ['zh-CN', 'en'], 6 | sourceLocale: 'zh-CN', 7 | catalogs: [ 8 | { 9 | path: '/src/locales/{locale}/messages', 10 | include: ['src'], 11 | }, 12 | ], 13 | format: 'po', 14 | }; 15 | 16 | export default conf; 17 | -------------------------------------------------------------------------------- /apps/web/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. 6 | -------------------------------------------------------------------------------- /apps/web/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | 'postcss-import': {}, 4 | 'tailwindcss/nesting': {}, 5 | tailwindcss: {}, 6 | autoprefixer: {}, 7 | ...(process.env.NODE_ENV === 'production' ? { cssnano: {} } : {}), 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /apps/web/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /api 3 | -------------------------------------------------------------------------------- /apps/web/src/app/children/riddle/print/page.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { RiddlePrintPage } from '@/components/children/RiddlePrintPage'; 3 | import { PageLayout } from '@/components/page/PageLayout'; 4 | import type { NextPageProps } from '@/types'; 5 | 6 | export default async function (props: NextPageProps) { 7 | return ( 8 | 9 | 10 | 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /apps/web/src/app/cn/id/page.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ChinaIdInfoPage } from '@/components/cn/ChinaIdInfoPage'; 3 | import { PageContainer } from '@/components/page/PageContainer'; 4 | import { PageLayout } from '@/components/page/PageLayout'; 5 | import type { NextPageProps } from '@/types'; 6 | 7 | export default async function (props: NextPageProps) { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/app/daisy/theme/page.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { DaisyThemePage } from '@/app/daisy/theme/DaisyThemePage'; 3 | import { PageContainer } from '@/components/page/PageContainer'; 4 | import { PageLayout } from '@/components/page/PageLayout'; 5 | import type { NextPageProps } from '@/types'; 6 | 7 | export default async function (props: NextPageProps) { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/app/error.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import React from 'react'; 4 | import { ServerErrorPlaceholder } from '@/components/NotFoundPlaceholder'; 5 | 6 | export default function ErrorPage() { 7 | return ; 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/apps/web/src/app/favicon.ico -------------------------------------------------------------------------------- /apps/web/src/app/hash/page.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { HashPage } from '@/components/hash/HashPage'; 3 | import { PageContainer } from '@/components/page/PageContainer'; 4 | import { PageLayout } from '@/components/page/PageLayout'; 5 | import type { NextPageProps } from '@/types'; 6 | 7 | export default async function (props: NextPageProps) { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/app/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/apps/web/src/app/icon.png -------------------------------------------------------------------------------- /apps/web/src/app/id/benchmark/page.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { IdBenchmarkPage } from '@/app/id/benchmark/IdBenchmarkPage'; 3 | import { PageContainer } from '@/components/page/PageContainer'; 4 | import { PageLayout } from '@/components/page/PageLayout'; 5 | 6 | export default function () { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/src/app/ipfs/gateway/check/page.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import IpfsGatewayCheck from '@/components/ipfs/gateway/IpfsGatewayCheck'; 3 | import { PageLayout } from '@/components/page/PageLayout'; 4 | 5 | export default function () { 6 | return ( 7 | 8 | 9 | 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /apps/web/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './globals.css'; 3 | import { NextRootLayout } from '@/app/NextRootLayout'; 4 | import type { NextLayoutProps } from '@/types'; 5 | 6 | export default async function RootLayout({ children, params }: NextLayoutProps) { 7 | return {children}; 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/src/app/nordvpn/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from 'next/navigation'; 2 | 3 | export default function () { 4 | redirect('/nordvpn/server/'); 5 | 6 | return null; 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/src/app/not-found.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import React from 'react'; 4 | import { PageContainer } from '@/components/page/PageContainer'; 5 | import { PageLayout } from '@/components/page/PageLayout'; 6 | 7 | export default function ErrorPage() { 8 | return ( 9 | 10 | 11 |

Not found

12 |
13 |
14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/app/password/hash/page.tsx: -------------------------------------------------------------------------------- 1 | import { PasswordHashContent } from './PasswordHashContent'; 2 | 3 | export default function () { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/password/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from 'next/navigation'; 2 | 3 | export default function () { 4 | redirect('/password/strength'); 5 | 6 | return null; 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/src/app/semver/page.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { PageContainer } from '@/components/page/PageContainer'; 3 | import { PageLayout } from '@/components/page/PageLayout'; 4 | import { SemverTool } from '@/components/semver/SemverTool'; 5 | import type { NextPageProps } from '@/types'; 6 | 7 | export default async function (props: NextPageProps) { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/app/utils.ts: -------------------------------------------------------------------------------- 1 | import { headers } from 'next/headers'; 2 | 3 | export async function getServerUrl() { 4 | const hdr = await headers(); 5 | return hdr.get('x-url'); 6 | } 7 | 8 | export async function getServerRequestPath() { 9 | let url = await getServerUrl(); 10 | if (url) { 11 | try { 12 | return new URL(url).pathname; 13 | } catch (e) {} 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/components/ContentContainer.tsx: -------------------------------------------------------------------------------- 1 | import React, { type PropsWithChildren } from 'react'; 2 | 3 | export const ContentContainer: React.FC = ({ children }) => { 4 | return
{children}
; 5 | }; 6 | -------------------------------------------------------------------------------- /apps/web/src/components/cn/code.ts: -------------------------------------------------------------------------------- 1 | export const IdTypes = { 2 | // 居民身份证号码 3 | 4 | USCI: { 5 | name: 'USCI', 6 | fullName: 'Unified Social Credit Identifier', 7 | label: '统一社会信用代码', 8 | length: 18, 9 | }, 10 | }; 11 | 12 | export interface Code { 13 | label: string; 14 | codes?: Record; 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/components/cn/gb11643/mod11.ts: -------------------------------------------------------------------------------- 1 | const _weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1]; 2 | const _table = [1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2]; 3 | 4 | export function mod11(s: string) { 5 | let sum = 0; 6 | for (let i = 0; i < s.length; i++) { 7 | sum += parseInt(s[i]) * _weights[i]; 8 | } 9 | sum %= 11; 10 | sum = _table[sum]; 11 | if (sum === 10) { 12 | return 'X'; 13 | } 14 | return sum.toString(); 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/components/cn/gb11643/mode11.test.ts: -------------------------------------------------------------------------------- 1 | import { assert, test } from 'vitest'; 2 | import { mod11 } from './mod11'; 3 | 4 | test('mod11', () => { 5 | for (const [s, r] of [['11010519491231002', 'X']]) { 6 | assert.equal(mod11(s), r); 7 | } 8 | }); 9 | -------------------------------------------------------------------------------- /apps/web/src/components/cn/gb31200/mod31.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from 'vitest'; 2 | import { mod31 } from './mod31'; 3 | 4 | test.fails('mod31', () => { 5 | // fixme mod 31 6 | expect(mod31('11610582435JGWXMU')).toBeFalsy(); 7 | }); 8 | -------------------------------------------------------------------------------- /apps/web/src/components/cn/gs15/BusinessLicenseNo.test.ts: -------------------------------------------------------------------------------- 1 | import { test } from 'vitest'; 2 | import { BusinessLicenseNo } from './BusinessLicenseNo'; 3 | 4 | test('BusinessLicenseNo', () => { 5 | BusinessLicenseNo.parse('330196000080659'); 6 | }); 7 | -------------------------------------------------------------------------------- /apps/web/src/components/cn/usci/checkUSCI.ts: -------------------------------------------------------------------------------- 1 | import { mod31, Mod31Numbers } from './mod31'; 2 | 3 | export function checkUSCI(s: string) { 4 | return Mod31Numbers[s[17]] === mod31(s.slice(0, 17)); 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/components/cn/usci/usci.test.ts: -------------------------------------------------------------------------------- 1 | import { assert, test } from 'vitest'; 2 | import { checkUSCI } from './checkUSCI'; 3 | import { randomUSCI } from './randomUSCI'; 4 | import { parseUSCI } from './usci'; 5 | 6 | test('verify', () => { 7 | assert.isTrue(checkUSCI('91310000775785552L')); 8 | assert.isTrue(checkUSCI('91350100M000100Y43')); 9 | assert.deepEqual(randomUSCI(parseUSCI('91350100M000100Y43')), parseUSCI('91350100M000100Y43')); 10 | assert.isTrue(checkUSCI(randomUSCI({}).raw)); 11 | }); 12 | -------------------------------------------------------------------------------- /apps/web/src/components/cn/utils/randomPick.ts: -------------------------------------------------------------------------------- 1 | export function randomPick(s: T[]) { 2 | return s[Math.floor(Math.random() * s.length)]; 3 | } 4 | -------------------------------------------------------------------------------- /apps/web/src/components/ipfs/buildIpfsLink.ts: -------------------------------------------------------------------------------- 1 | import { useIpfsGatewayState } from './gateway'; 2 | 3 | export function buildIpfsLink({ gateway = useIpfsGatewayState().prefer, hash }: { gateway?: string; hash: string }) { 4 | return gateway.replace(':hash', hash); 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/components/page/PageContainer.tsx: -------------------------------------------------------------------------------- 1 | import React, { Suspense, type ComponentPropsWithoutRef, type FC } from 'react'; 2 | import { cn } from '@wener/console'; 3 | import { LoadingIndicator } from '@wener/console/loader'; 4 | 5 | export const PageContainer: FC> = ({ children, className }) => { 6 | return ( 7 |
8 | }>{children} 9 |
10 | ); 11 | }; 12 | -------------------------------------------------------------------------------- /apps/web/src/components/page/PageLayout/index.ts: -------------------------------------------------------------------------------- 1 | export { PageLayout } from './PageLayout'; 2 | -------------------------------------------------------------------------------- /apps/web/src/data/getSiteData.ts: -------------------------------------------------------------------------------- 1 | export function getSiteData() { 2 | return { 3 | title: 'Wener', 4 | url: 'https://apis.wener.me', 5 | }; 6 | } 7 | -------------------------------------------------------------------------------- /apps/web/src/i18n/getLocales.ts: -------------------------------------------------------------------------------- 1 | const locales = ['zh-CN', 'en']; 2 | const defaultLocale = 'zh-CN'; 3 | 4 | export function getLocales() { 5 | return { 6 | locales, 7 | defaultLocale, 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /apps/web/src/i18n/index.tsx: -------------------------------------------------------------------------------- 1 | export { resolveLocale } from './resolveLocale'; 2 | 3 | export { loadMessage } from '@/i18n/loadMessage'; 4 | export { getLocales } from '@/i18n/getLocales'; 5 | export { loadI18n } from '@/i18n/loadI18n'; 6 | 7 | export { I18nServerProvider } from './I18nServerProvider'; 8 | 9 | export { resolveRequestLocale } from './resolveRequestLocale'; 10 | export { resolveClientLocale } from './resolveClientLocale'; 11 | -------------------------------------------------------------------------------- /apps/web/src/i18n/resolveLocale.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from 'vitest'; 2 | import { resolveLocale } from '@/i18n/resolveLocale'; 3 | 4 | test('resolveLocale', () => { 5 | expect(resolveLocale('zh')).toMatchObject({ 6 | locale: 'zh-CN', 7 | }); 8 | expect(resolveLocale('en-US')).toMatchObject({ 9 | locale: 'en', 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /apps/web/src/i18n/resolveLocale.ts: -------------------------------------------------------------------------------- 1 | import { match } from '@formatjs/intl-localematcher'; 2 | import { getLocales } from '@/i18n/getLocales'; 3 | 4 | export function resolveLocale(locale?: string | null) { 5 | const { locales, defaultLocale } = getLocales(); 6 | try { 7 | locale = match([locale || locales[0]], locales, defaultLocale); 8 | } catch (e) { 9 | locale = defaultLocale; 10 | } 11 | return { 12 | locale, 13 | locales, 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/locales/en/messages.mjs: -------------------------------------------------------------------------------- 1 | /*eslint-disable*/export const messages=JSON.parse("{\"eHK0D4\":\"IPFS Gateway Checker\",\"tags.web\":\"Web\",\"sCUSes\":\"Zxcvbn Password Strength\",\"home.hero.more\":\"Learn more\",\"tags.children\":\"Children\",\"home.entrypoint.title\":\"Entrypoint\",\"home.hero.intro\":\"I like writing code and exploring new technologies. This is the playground for <0>wenerme/wode.\",\"home.tag.all\":\"All\",\"entry.semver.title\":\"Semantic Versioning\",\"page.nav.language\":\"Language\"}"); -------------------------------------------------------------------------------- /apps/web/src/locales/zh-CN/messages.mjs: -------------------------------------------------------------------------------- 1 | /*eslint-disable*/export const messages=JSON.parse("{\"eHK0D4\":\"IPFS 网关检测\",\"tags.web\":\"Web技术\",\"sCUSes\":\"Zxcvbn 密码强度检测\",\"home.hero.more\":\"了解更多\",\"tags.children\":\"儿童\",\"home.entrypoint.title\":\"入口\",\"home.hero.intro\":\"我喜欢编写代码和探索新技术。这是<0>wenerme/wode的游乐场。\",\"home.tag.all\":\"所有\",\"entry.semver.title\":\"语义版本\",\"page.nav.language\":\"语言\"}"); -------------------------------------------------------------------------------- /apps/web/src/types.ts: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import type { MaybePromise } from '@wener/utils'; 3 | 4 | export interface NextPageProps

, S = Record> { 5 | params: P; 6 | searchParams: MaybePromise; 7 | } 8 | 9 | export interface NextLayoutProps

> { 10 | params: MaybePromise

; 11 | children?: React.ReactNode; 12 | } 13 | -------------------------------------------------------------------------------- /buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v2 2 | clean: true 3 | managed: 4 | enabled: true 5 | disable: 6 | - path: protos/bundles 7 | plugins: 8 | - local: ./node_modules/.bin/protoc-gen-es 9 | out: packages/common/src/gen/pb 10 | inputs: 11 | - directory: protos/wode 12 | paths: 13 | - protos/wode/wode/foundation/v1 14 | - protos/wode/wode/service/v1 15 | - protos/wode/wode/incs/zhb/ve/v1 16 | -------------------------------------------------------------------------------- /components/wener-tiptap/.npmignore: -------------------------------------------------------------------------------- 1 | *.tsbuildinfo 2 | dist/report 3 | -------------------------------------------------------------------------------- /components/wener-tiptap/Makefile: -------------------------------------------------------------------------------- 1 | REPO_ROOT ?= $(shell git rev-parse --show-toplevel) 2 | -include $(REPO_ROOT)/node.mk 3 | -------------------------------------------------------------------------------- /components/wener-tiptap/index.ts: -------------------------------------------------------------------------------- 1 | export * from './src' 2 | -------------------------------------------------------------------------------- /components/wener-tiptap/rollup.bundle.mjs: -------------------------------------------------------------------------------- 1 | import { prod } from '@wener/wode/rollup.mjs'; 2 | export default prod; 3 | -------------------------------------------------------------------------------- /components/wener-tiptap/rollup.dev.mjs: -------------------------------------------------------------------------------- 1 | import { dev } from '@wener/wode/rollup.mjs'; 2 | export default dev; 3 | -------------------------------------------------------------------------------- /components/wener-tiptap/src/extensions/BoldExtension.ts: -------------------------------------------------------------------------------- 1 | import { Bold } from '@tiptap/extension-bold'; 2 | 3 | export const BoldExtension = Bold.extend({ 4 | renderMarkdown: { 5 | open: '**', 6 | close: '**', 7 | mixable: true, 8 | expelEnclosingWhitespace: true, 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /components/wener-tiptap/src/extensions/ItalicExtension.ts: -------------------------------------------------------------------------------- 1 | import { Italic } from '@tiptap/extension-italic'; 2 | 3 | export const ItalicExtension = Italic.extend({ 4 | renderMarkdown: { 5 | open: '_', 6 | close: '_', 7 | mixable: true, 8 | expelEnclosingWhitespace: true, 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /components/wener-tiptap/src/extensions/StrikeExtension.ts: -------------------------------------------------------------------------------- 1 | import { Strike } from '@tiptap/extension-strike'; 2 | 3 | export const StrikeExtension = Strike.extend({ 4 | renderMarkdown: { 5 | open: '~~', 6 | close: '~~', 7 | mixable: true, 8 | expelEnclosingWhitespace: true, 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /components/wener-tiptap/src/extensions/document.ts: -------------------------------------------------------------------------------- 1 | import { mergeAttributes, Node } from '@tiptap/core'; 2 | 3 | export const Document = Node.create({ 4 | name: 'doc', 5 | topNode: true, 6 | content: 'block+', 7 | 8 | addOptions() { 9 | return { 10 | HTMLAttributes: {}, 11 | }; 12 | }, 13 | 14 | parseHTML() { 15 | return [{ tag: 'article' }]; 16 | }, 17 | 18 | renderHTML({ HTMLAttributes }) { 19 | return ['article', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)]; 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /components/wener-tiptap/src/extensions/markdown.test.ts.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/components/wener-tiptap/src/extensions/markdown.test.ts.snap -------------------------------------------------------------------------------- /packages/common/.prettierignore: -------------------------------------------------------------------------------- 1 | .next 2 | build 3 | dist 4 | node_modules 5 | ignored 6 | src/gen 7 | -------------------------------------------------------------------------------- /packages/common/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /packages/common/src/ai/cv/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './types'; 2 | -------------------------------------------------------------------------------- /packages/common/src/aports/index.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /packages/common/src/components/index.ts: -------------------------------------------------------------------------------- 1 | export { useInit } from './useInit'; 2 | -------------------------------------------------------------------------------- /packages/common/src/components/useInit.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | import { runInit, type InitDef } from '@wener/common/meta'; 3 | 4 | export function useInit(init?: InitDef[]) { 5 | const [state, setState] = useState({ done: false }); 6 | useEffect(() => { 7 | runInit(init).finally(() => { 8 | setState({ done: true }); 9 | }); 10 | }, []); 11 | return state; 12 | } 13 | -------------------------------------------------------------------------------- /packages/common/src/icons/README.md: -------------------------------------------------------------------------------- 1 | - https://www.iconfont.cn/ 2 | -------------------------------------------------------------------------------- /packages/common/src/icons/svg/brands/DingtalkBrandIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/common/src/icons/svg/icons/DarkModeFilled.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/common/src/icons/svg/icons/LightModeFilled.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/common/src/npm/createBearerAuthFetch.ts: -------------------------------------------------------------------------------- 1 | import type { SimpleFetch } from './Unpkg'; 2 | 3 | export function createBearerAuthFetch(token: string | (() => string), fetch: SimpleFetch = globalThis.fetch) { 4 | return (url: string, init?: RequestInit) => { 5 | return fetch(url, { 6 | ...init, 7 | headers: { 8 | ...init?.headers, 9 | Authorization: `Bearer ${typeof token === 'function' ? token() : token}`, 10 | }, 11 | }); 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /packages/common/src/npm/index.ts: -------------------------------------------------------------------------------- 1 | export { Unpkg, type InitUnpkgOptions } from './Unpkg'; 2 | export { type UnpkgStorage } from './UnpkgStorage'; 3 | export { type PackageJson } from './PackageJson'; 4 | export { type RegistryPackage } from './RegistryPackage'; 5 | 6 | export { getContentType } from './mime'; 7 | -------------------------------------------------------------------------------- /packages/common/src/npm/server.ts: -------------------------------------------------------------------------------- 1 | export { createUnpkg, type CreateUnpkgOptions } from './createUnpkg'; 2 | export { createUnpkgHandler, type CreateUnpkgHandlerOptions } from './createUnpkgHandler'; 3 | export { createBearerAuthFetch } from './createBearerAuthFetch'; 4 | export { SQLiteStorage, type SQLiteStorageOptions } from './SQLiteStorage'; 5 | -------------------------------------------------------------------------------- /packages/common/src/npm/typedoc.ts: -------------------------------------------------------------------------------- 1 | export * from './index'; 2 | export * from './server'; 3 | -------------------------------------------------------------------------------- /packages/common/src/poc/alpine/README.md: -------------------------------------------------------------------------------- 1 | - https://github.com/wenerme/apki/blob/main/pkg/apki/models/package_index.go 2 | - https://github.com/alpinelinux/alpine-mirror-status 3 | 4 | ``` 5 | alpine/v3.19/main/x86/APKINDEX.tar.gz 6 | ``` 7 | -------------------------------------------------------------------------------- /packages/common/src/poc/alpine/main.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/packages/common/src/poc/alpine/main.ts -------------------------------------------------------------------------------- /packages/common/src/poc/alpine/repo/fs.ts: -------------------------------------------------------------------------------- 1 | import path from 'node:path'; 2 | 3 | export function getAlpineCacheDir(...paths: string[]) { 4 | let dir = '/tmp/cache/alpine'; 5 | if (paths.length) { 6 | path.join(dir, ...paths); 7 | } 8 | return dir; 9 | } 10 | -------------------------------------------------------------------------------- /packages/common/src/poc/alpine/service/ApkIndexService.ts: -------------------------------------------------------------------------------- 1 | import { MikroORM } from '@mikro-orm/postgresql'; 2 | import { Inject, Injectable } from '@nestjs/common'; 3 | import { EntityBaseService } from '@/entity/service/EntityBaseService'; 4 | import { ApkIndexEntity } from '../entity/ApkIndexEntity'; 5 | 6 | @Injectable() 7 | export class ApkIndexService extends EntityBaseService { 8 | constructor(@Inject(MikroORM) protected readonly orm: MikroORM) { 9 | super(orm, ApkIndexEntity); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/common/src/poc/bbvm/BasicGuiRuntime.ts: -------------------------------------------------------------------------------- 1 | import { BaseRuntime } from './BaseRuntime'; 2 | 3 | export class BasicGuiRuntime extends BaseRuntime { 4 | scale = 2; 5 | width = 240; 6 | height = 320; 7 | 8 | px = (x: number) => x * this.scale; 9 | } 10 | -------------------------------------------------------------------------------- /packages/common/src/poc/bbvm/CanvasRuntime.ts: -------------------------------------------------------------------------------- 1 | import { BasicGuiRuntime } from './BasicGuiRuntime'; 2 | 3 | export class CanvasRuntime extends BasicGuiRuntime { 4 | ctx!: CanvasRenderingContext2D; 5 | 6 | flush() { 7 | const { ctx, px } = this; 8 | const { width, height } = ctx.canvas; 9 | ctx.fillStyle = 'black'; 10 | ctx.fillRect(0, 0, width, height); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/common/src/poc/bbvm/README.md: -------------------------------------------------------------------------------- 1 | - https://github.com/wenerme/bbvm 2 | - https://github.com/wenerme/bbvm-test 3 | -------------------------------------------------------------------------------- /packages/common/src/poc/bbvm/bbasm/Makefile: -------------------------------------------------------------------------------- 1 | gen: 2 | npx -y peggy $(PWD)/bbasm.pegjs -o $(PWD)/parser.js --format es --allowed-start-rules Grammar,Assembly 3 | npx prettier -w $(PWD)/parser.js # .js.map 失效 4 | -------------------------------------------------------------------------------- /packages/common/src/poc/bbvm/bbvm.main.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import { runBbvm } from './runBbvm'; 3 | 4 | await runBbvm(); 5 | -------------------------------------------------------------------------------- /packages/common/src/poc/bbvm/lib.ts: -------------------------------------------------------------------------------- 1 | export function float32bits(v: number) { 2 | const buf = new ArrayBuffer(4); 3 | new Float32Array(buf)[0] = v; 4 | return new Uint32Array(buf)[0]; 5 | } 6 | 7 | export function float32frombits(v: number) { 8 | const buf = new ArrayBuffer(4); 9 | new Uint32Array(buf)[0] = v; 10 | return new Float32Array(buf)[0]; 11 | } 12 | -------------------------------------------------------------------------------- /packages/common/src/poc/bbvm/rlb/index.ts: -------------------------------------------------------------------------------- 1 | export { loadImages, type ImageInfo } from './rlb'; 2 | -------------------------------------------------------------------------------- /packages/common/src/poc/cli/wec.main.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import { createWecCommand } from './createWecCommand'; 3 | import { runCommand } from './run'; 4 | 5 | runCommand(createWecCommand()); 6 | -------------------------------------------------------------------------------- /packages/common/src/poc/contracts/Makefile: -------------------------------------------------------------------------------- 1 | SHELL:=env bash -O extglob -O globstar 2 | 3 | gen-typechain: 4 | mkdir -p ./generated 5 | rm -rf ./generated/* 6 | npx -y typechain --target=ethers-v6 --discriminate-types --out-dir $(PWD)/generated "$(PWD)/abi/*.json" 7 | 8 | install: 9 | pnpm add -D @typechain/ethers-v6 typechain 10 | 11 | clean: 12 | rm -rf ./generated/* 13 | rm -rf ./abi/* 14 | -------------------------------------------------------------------------------- /packages/common/src/poc/domains/README.md: -------------------------------------------------------------------------------- 1 | - https://github.com/v2fly/domain-list-community 2 | -------------------------------------------------------------------------------- /packages/common/src/poc/fs/README.md: -------------------------------------------------------------------------------- 1 | - https://github.com/streamich/memfs 2 | -------------------------------------------------------------------------------- /packages/common/src/poc/ldap/README.md: -------------------------------------------------------------------------------- 1 | - [glauth/glauth](https://github.com/glauth/glauth) 2 | - MIT, Go 3 | - LDAP server for development, home use, or CI 4 | - 支持能力管理 5 | - [nitnelave/lldap](https://github.com/nitnelave/lldap) 6 | - GPLv3, Rust 7 | - GraphQL - https://github.com/nitnelave/lldap/blob/main/schema.graphql 8 | - JWT Auth 9 | - WebUI 管理用户 10 | - 不支持 LDAPS, HTTPS 11 | - [majewsky/portunus](https://github.com/majewsky/portunus) 12 | - GPLv3, Go 13 | -------------------------------------------------------------------------------- /packages/common/src/poc/netflix/netflix.test.ts: -------------------------------------------------------------------------------- 1 | import { test } from 'vitest'; 2 | import { verifyNetflixProxy } from './verifyNetflixProxy'; 3 | 4 | test( 5 | 'verify', 6 | async () => { 7 | console.log( 8 | await verifyNetflixProxy({ 9 | proxy: `http://127.0.0.1:7890`, 10 | }), 11 | ); 12 | }, 13 | { 14 | timeout: 60_000, 15 | }, 16 | ); 17 | -------------------------------------------------------------------------------- /packages/common/src/poc/nordvpn/README.md: -------------------------------------------------------------------------------- 1 | - https://nordvpn.com/api/server/stats 2 | - https://nordvpn.com/api/server 3 | - https://api.nordvpn.com/v1/servers/countries 4 | - https://api.nordvpn.com/v1/servers 5 | - ?limit=9999999 6 | - https://nordvpn.com/wp-admin/admin-ajax.php?action=servers_recommendations 7 | -------------------------------------------------------------------------------- /packages/common/src/poc/storage/README.md: -------------------------------------------------------------------------------- 1 | - localForge 2 | - https://github.com/FrigadeHQ/remote-storage 3 | - https://github.com/jaredwray/keyv 4 | 5 | ## Serialize 6 | 7 | - https://github.com/localForage/localForage/blob/master/src/utils/serializer.js 8 | - https://github.com/blitz-js/superjson 9 | - https://github.com/yahoo/serialize-javascript 10 | - https://github.com/Rich-Harris/devalue 11 | -------------------------------------------------------------------------------- /packages/common/src/poc/storage/serialize.ts: -------------------------------------------------------------------------------- 1 | export function serialize() {} 2 | 3 | export function deserialize() {} 4 | -------------------------------------------------------------------------------- /packages/common/src/schemas/gen.test.ts: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs/promises'; 2 | import { test } from 'vitest'; 3 | import { generateSchema } from './generateSchema'; 4 | 5 | test('schema/gen', async ({}) => { 6 | const __dirname = new URL('.', import.meta.url).pathname; 7 | const files = await fs.readdir(__dirname); 8 | for (let file of files) { 9 | if (!file.endsWith('d.ts')) { 10 | continue; 11 | } 12 | 13 | await generateSchema({ 14 | file: `${__dirname}/${file}`, 15 | }); 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /packages/common/src/schemas/index.ts: -------------------------------------------------------------------------------- 1 | export { WellKnownSchemas, UUID, USCI, ULID, PhoneNumber, TelNumber, ChinaCitizenID } from './well-known'; 2 | -------------------------------------------------------------------------------- /packages/common/src/schemas/wode.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @title 启用 3 | */ 4 | type ResourceStateActive = 'Active'; 5 | /** 6 | * @title 禁用 7 | */ 8 | type ResourceStateInactive = 'Inactive'; 9 | 10 | /** 11 | * @title 资源状态 12 | * @$id wode.resource.ResourceState 13 | */ 14 | export type ResourceState = ResourceStateActive | ResourceStateInactive; 15 | -------------------------------------------------------------------------------- /packages/common/src/schemas/zod/wode.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | 3 | export type ResourceStateActive = z.infer; 4 | export const ResourceStateActive = z.literal('Active'); 5 | 6 | export type ResourceStateInactive = z.infer; 7 | export const ResourceStateInactive = z.literal('Inactive'); 8 | 9 | export type ResourceState = z.infer; 10 | export const ResourceState = z.union([ResourceStateActive, ResourceStateInactive]); 11 | -------------------------------------------------------------------------------- /packages/common/src/torrent/fixtures/bitlove-intro.torrent: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/packages/common/src/torrent/fixtures/bitlove-intro.torrent -------------------------------------------------------------------------------- /packages/common/src/torrent/fixtures/leaves-duplicate-tracker.torrent: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/packages/common/src/torrent/fixtures/leaves-duplicate-tracker.torrent -------------------------------------------------------------------------------- /packages/common/src/torrent/fixtures/leaves-empty-announce-list.torrent: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/packages/common/src/torrent/fixtures/leaves-empty-announce-list.torrent -------------------------------------------------------------------------------- /packages/common/src/torrent/fixtures/leaves-empty-url-list.torrent: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/packages/common/src/torrent/fixtures/leaves-empty-url-list.torrent -------------------------------------------------------------------------------- /packages/common/src/torrent/fixtures/leaves-url-list.torrent: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/packages/common/src/torrent/fixtures/leaves-url-list.torrent -------------------------------------------------------------------------------- /packages/common/svgo.config.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | 'plugins': [ 3 | 'preset-default', 4 | { 5 | 'name': 'removeAttrs', 6 | 'params': { 7 | 'attrs': [ 8 | 'data-.*', 9 | ], 10 | }, 11 | }, 12 | { 13 | 'name': 'sortAttrs', 14 | }, 15 | ], 16 | }; 17 | -------------------------------------------------------------------------------- /packages/common/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config'; 2 | 3 | export default defineConfig({ 4 | test: { 5 | alias: { 6 | '@/': new URL('./src/', import.meta.url).pathname, 7 | }, 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /packages/system/Makefile: -------------------------------------------------------------------------------- 1 | REPO_ROOT ?= $(shell git rev-parse --show-toplevel) 2 | -include $(REPO_ROOT)/node.mk 3 | -------------------------------------------------------------------------------- /packages/system/index.ts: -------------------------------------------------------------------------------- 1 | export * from './src'; 2 | -------------------------------------------------------------------------------- /packages/system/rollup.bundle.mjs: -------------------------------------------------------------------------------- 1 | import { prod } from '@wener/wode/rollup.mjs'; 2 | 3 | export default prod 4 | -------------------------------------------------------------------------------- /packages/system/rollup.dev.mjs: -------------------------------------------------------------------------------- 1 | import { dev } from '@wener/wode/rollup.mjs'; 2 | 3 | export default dev 4 | -------------------------------------------------------------------------------- /packages/system/server.ts: -------------------------------------------------------------------------------- 1 | export * from './src/server'; 2 | -------------------------------------------------------------------------------- /packages/system/src/index.ts: -------------------------------------------------------------------------------- 1 | export { getGlobalSystem, type SystemJS, type ImportMap } from './utils/getGlobalSystem'; 2 | export { resolve, legacy } from './utils/resolve'; 3 | export { addPreload } from './utils/addPreload'; 4 | 5 | export { resolveBareSpecifier } from './hooks/resolveBareSpecifier'; 6 | export { instantiatePackageProtocol } from './hooks/instantiatePackageProtocol'; 7 | export { loadBrowserSystem } from './loaders/loadBrowserSystem'; 8 | export { type SystemHookOption, hookSystem } from './loaders/hookSystem'; 9 | -------------------------------------------------------------------------------- /packages/system/src/server.ts: -------------------------------------------------------------------------------- 1 | export { loadServerSystem } from './loaders/loadServerSystem'; 2 | -------------------------------------------------------------------------------- /packages/system/src/typedoc.ts: -------------------------------------------------------------------------------- 1 | export * from './index'; 2 | export * from './server'; 3 | -------------------------------------------------------------------------------- /packages/wener-client/.env: -------------------------------------------------------------------------------- 1 | DB_TYPE= 2 | DB_DSN= 3 | 4 | # Wechat 5 | WX_PROXY= 6 | WX_APP_ID= 7 | WX_APP_SECRET= 8 | WX_APP_SECRET_FILE= 9 | 10 | # WeWorkFinanceClient 11 | WWF_CORP_ID= 12 | WWF_CORP_SECRET= 13 | WWF_PRIVATE_KEY= 14 | WWF_PROXY= 15 | WWF_PROXY_CREDENTIAL= 16 | WWF_TIMEOUT= 17 | WWF_PRIVATE_KEY_FILE= 18 | -------------------------------------------------------------------------------- /packages/wener-client/.gitignore: -------------------------------------------------------------------------------- 1 | /tests 2 | /*.json 3 | -------------------------------------------------------------------------------- /packages/wener-client/libs/WeWorkFinanceSdk/Makefile: -------------------------------------------------------------------------------- 1 | checksum: 2 | md5sum -c ./md5.txt 3 | -------------------------------------------------------------------------------- /packages/wener-client/libs/WeWorkFinanceSdk/README.md: -------------------------------------------------------------------------------- 1 | # WeWorkFinanceClient 2 | 3 | - for WeWorkFinanceClient 4 | - only works for glibc, amd64, linux 5 | - reference 6 | - https://developer.work.weixin.qq.com/document/path/91774 7 | - download sdk 8 | 9 | 10 | ```bash 11 | # do checksum for libWeWorkFinanceSdk_C.so 12 | make checksum 13 | ``` 14 | -------------------------------------------------------------------------------- /packages/wener-client/libs/WeWorkFinanceSdk/libWeWorkFinanceSdk_C.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/packages/wener-client/libs/WeWorkFinanceSdk/libWeWorkFinanceSdk_C.so -------------------------------------------------------------------------------- /packages/wener-client/libs/WeWorkFinanceSdk/md5.txt: -------------------------------------------------------------------------------- 1 | d422224e67eb07a195d1d7115b39284c libWeWorkFinanceSdk_C.so 2 | -------------------------------------------------------------------------------- /packages/wener-client/libs/WeWorkFinanceSdk/version.txt: -------------------------------------------------------------------------------- 1 | 20240606 2 | -------------------------------------------------------------------------------- /packages/wener-client/src/17dz/README.md: -------------------------------------------------------------------------------- 1 | - https://www.17dz.com/ 2 | - https://www.17win.com/ 3 | - 统计请求,可以屏蔽域名 https://mdtj.17win.com/mars/general/batch/collect 4 | - 区域代码 5 | - https://openapi.17win.com/dict/dictFacade/getListByParentCode?parentCode=000000&type=taxArea 6 | - 4007112366.com 7 | 8 | ## 组织 9 | 10 | - getGroupList 获取所有组织 11 | - 会话里有 bizId 和 companyId 12 | - changeGroup 切换组织 - 切换后 companyId 会变 13 | - AccountSet - 账套 14 | -------------------------------------------------------------------------------- /packages/wener-client/src/17dz/crypto/crypto.test.ts: -------------------------------------------------------------------------------- 1 | import { assert, test } from 'vitest'; 2 | import { decrypt } from './decrypt'; 3 | import { encrypt } from './index'; 4 | 5 | test('crypto', () => { 6 | assert.equal(decrypt('Q5ewARAK1rrqr0DlCUqGfQ=='), ''); 7 | assert.equal(encrypt(''), 'Q5ewARAK1rrqr0DlCUqGfQ=='); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/wener-client/src/17dz/crypto/getCryptoKey.ts: -------------------------------------------------------------------------------- 1 | import Utf8 from 'crypto-js/enc-utf8'; 2 | 3 | // https://17dz.com/iit-yqdz-web-pc/router.bundle.js enc.Utf8.parse 4 | const key = Utf8.parse('RGZwrjvQmQl2A4Hk'); 5 | 6 | export function getCryptoKey() { 7 | return key; 8 | } 9 | -------------------------------------------------------------------------------- /packages/wener-client/src/17dz/crypto/index.ts: -------------------------------------------------------------------------------- 1 | export { encrypt } from './encrypt'; 2 | export { decrypt } from './decrypt'; 3 | export { getCryptoKey } from './getCryptoKey'; 4 | -------------------------------------------------------------------------------- /packages/wener-client/src/17dz/errors.ts: -------------------------------------------------------------------------------- 1 | export class UnauthenticatedError extends Error { 2 | code?: string; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/wener-client/src/17dz/flow/index.ts: -------------------------------------------------------------------------------- 1 | export { runLoginFlow, getSession, type RunLoginFlowOptions } from './login'; 2 | -------------------------------------------------------------------------------- /packages/wener-client/src/17dz/flow/login/const.ts: -------------------------------------------------------------------------------- 1 | export const YqdzUrls = { 2 | login: 'https://17dz.com/home/login.html', 3 | admin: 'https://17dz.com/manage/index.html', 4 | } as const; 5 | -------------------------------------------------------------------------------- /packages/wener-client/src/17dz/flow/login/cookieToString.ts: -------------------------------------------------------------------------------- 1 | export function cookieToString(cookie?: Array<{ name: string; value: string }>): string { 2 | return cookie?.map((v) => `${v.name}=${v.value}`).join('; ') || ''; 3 | } 4 | -------------------------------------------------------------------------------- /packages/wener-client/src/17dz/flow/login/index.ts: -------------------------------------------------------------------------------- 1 | export { runLoginFlow, type RunLoginFlowOptions } from './runLoginFlow'; 2 | export { getSession } from './getSession'; 3 | -------------------------------------------------------------------------------- /packages/wener-client/src/17dz/index.ts: -------------------------------------------------------------------------------- 1 | export { Client } from './Client'; 2 | export { request, type RequestOptions } from './request'; 3 | export { sign } from './sign'; 4 | export { UnauthenticatedError } from './errors'; 5 | export type * from './types'; 6 | -------------------------------------------------------------------------------- /packages/wener-client/src/17dz/operator/getLoginSession.ts: -------------------------------------------------------------------------------- 1 | import type { FetchLike } from '@wener/utils'; 2 | import { requestFromSession } from './requestFromSession'; 3 | import type { GetLoginSessionResponse } from './types'; 4 | 5 | export async function getLoginSession({ fetch, cookie }: { fetch?: FetchLike; cookie: string }) { 6 | return requestFromSession({ 7 | url: 'https://17dz.com/xqy-portal-web/activity/activity/login/getLoginSession', 8 | cookie, 9 | fetch, 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /packages/wener-client/src/17dz/operator/index.ts: -------------------------------------------------------------------------------- 1 | export { requestFromSession, type SessionRequestOptions } from './requestFromSession'; 2 | export { OperatorClient, type OperatorClientOptions } from './OperatorClient'; 3 | export { getLoginSession } from './getLoginSession'; 4 | export type * from './types'; 5 | -------------------------------------------------------------------------------- /packages/wener-client/src/alicloud/apis.ts: -------------------------------------------------------------------------------- 1 | import type * as DytnsV20200217 from './DytnsV20200217'; 2 | import type * as OcrV20210707 from './OcrV20210707'; 3 | 4 | export interface AliCloudApis { 5 | Dytnsapi: { 6 | '2020-02-17': DytnsV20200217.DytnsV20200217Api; 7 | }; 8 | 'ocr-api': { 9 | '2021-07-07': OcrV20210707.OcrV20210707Api; 10 | }; 11 | } 12 | 13 | export * as OcrV20210707 from './OcrV20210707'; 14 | export * as DytnsV20200217 from './DytnsV20200217'; 15 | -------------------------------------------------------------------------------- /packages/wener-client/src/alicloud/index.ts: -------------------------------------------------------------------------------- 1 | export * from './request'; 2 | export * from './signv3'; 3 | export * from './apis'; 4 | 5 | export * from './AliCloudClient'; 6 | -------------------------------------------------------------------------------- /packages/wener-client/src/baidu/ce/index.ts: -------------------------------------------------------------------------------- 1 | export { getAccessToken, type GetAccessTokenPayload } from './getAccessToken'; 2 | -------------------------------------------------------------------------------- /packages/wener-client/src/browser/index.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /packages/wener-client/src/browser/launch/index.ts: -------------------------------------------------------------------------------- 1 | export { launch, type LaunchOptions } from './launch'; 2 | export { connect } from './connect'; 3 | -------------------------------------------------------------------------------- /packages/wener-client/src/cubejs/README.md: -------------------------------------------------------------------------------- 1 | # cubejs 2 | 3 | minimal rest client + typings for cubejs 4 | 5 | - https://github.com/cube-js/cube/blob/master/packages/cubejs-client-core/README.md 6 | - https://cube.dev/docs/product/apis-integrations/rest-api/query-format 7 | -------------------------------------------------------------------------------- /packages/wener-client/src/cubejs/index.ts: -------------------------------------------------------------------------------- 1 | export { CubeClient, type CubeClientOptions } from './CubeClient'; 2 | export type * from './types'; 3 | -------------------------------------------------------------------------------- /packages/wener-client/src/cubejs/service.ts: -------------------------------------------------------------------------------- 1 | import type { Query } from './types'; 2 | 3 | export interface CubeLoadResponse {} 4 | 5 | export interface CubeLoadRequest { 6 | query: Query | Query[]; 7 | } 8 | -------------------------------------------------------------------------------- /packages/wener-client/src/feishu/document/block/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Block'; 2 | -------------------------------------------------------------------------------- /packages/wener-client/src/feishu/document/index.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /packages/wener-client/src/feishu/index.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /packages/wener-client/src/funasr/index.ts: -------------------------------------------------------------------------------- 1 | export { requestOffline } from './requestOffline'; 2 | export type * from './types'; 3 | -------------------------------------------------------------------------------- /packages/wener-client/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ValueHolder'; 2 | export * from './ExpiryValue'; 3 | -------------------------------------------------------------------------------- /packages/wener-client/src/openai/OpenAiClientError.ts: -------------------------------------------------------------------------------- 1 | import type { ErrorResponse } from './request'; 2 | 3 | export class OpenAiClientError extends Error { 4 | readonly type: string; 5 | readonly code: string; 6 | readonly param: string | undefined; 7 | 8 | constructor({ message, type, code, param }: ErrorResponse['error']) { 9 | super(message); 10 | this.type = type; 11 | this.code = code; 12 | this.param = param; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/wener-client/src/openai/gen.test.ts: -------------------------------------------------------------------------------- 1 | import { TypeGen } from '@wener/utils/schema/typebox/gen'; 2 | import { test } from 'vitest'; 3 | 4 | test('gen', () => { 5 | TypeGen.TypeScriptToTypeBox.Generate(` 6 | interface HI { 7 | name: string 8 | } 9 | `); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/wener-client/src/openai/index.ts: -------------------------------------------------------------------------------- 1 | export * from './OpenAiClient'; 2 | export * from './types'; 3 | export * from './request'; 4 | export { OpenAiClientError } from './OpenAiClientError'; 5 | -------------------------------------------------------------------------------- /packages/wener-client/src/openai/messages.ts: -------------------------------------------------------------------------------- 1 | export type CreateEmbeddingRequest = { 2 | input: string | string[]; 3 | model: string; 4 | encoding_format?: 'float' | 'base64'; 5 | user?: string; 6 | }; 7 | -------------------------------------------------------------------------------- /packages/wener-client/src/qq/index.ts: -------------------------------------------------------------------------------- 1 | export { parseEmotion, getEmotions } from './utils/parseEmotion'; 2 | -------------------------------------------------------------------------------- /packages/wener-client/src/server/index.ts: -------------------------------------------------------------------------------- 1 | export * from './createFileExpiryValue'; 2 | -------------------------------------------------------------------------------- /packages/wener-client/src/wechat/README.md: -------------------------------------------------------------------------------- 1 | - 小程序 2 | - API https://developers.weixin.qq.com/miniprogram/dev/api/ 3 | - 服务端 https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/ 4 | - https://api.weixin.qq.com/cgi-bin/token 5 | -------------------------------------------------------------------------------- /packages/wener-client/src/wechat/getRedirectUri.ts: -------------------------------------------------------------------------------- 1 | import { getGlobalThis } from '@wener/utils'; 2 | 3 | export function getRedirectUri(u?: string) { 4 | u ||= getGlobalThis().location?.href; 5 | if (!u) { 6 | return; 7 | } 8 | 9 | const url = new URL(u); 10 | url.search = ''; 11 | url.hash = ''; 12 | return url.toString(); 13 | } 14 | -------------------------------------------------------------------------------- /packages/wener-client/src/wechat/getWxJsSdk.ts: -------------------------------------------------------------------------------- 1 | import type { WxJsSdk } from './WxJsSdk'; 2 | 3 | export function getWxJsSdk(): WxJsSdk { 4 | return globalThis.window?.wx; 5 | } 6 | -------------------------------------------------------------------------------- /packages/wener-client/src/wechat/miniprogram/index.ts: -------------------------------------------------------------------------------- 1 | export { decryptData } from './decryptData'; 2 | export { verifySignature } from './crypto'; 3 | export type * from './types'; 4 | -------------------------------------------------------------------------------- /packages/wener-client/src/wechat/server/index.ts: -------------------------------------------------------------------------------- 1 | export * from './WechatConfig'; 2 | 3 | export { request, type RequestOptions } from './request'; 4 | export { getStableAccessToken, getAccessToken, code2session } from './getAccessToken'; 5 | export { WechatServerClient, type WechatServerClientOptions, type WechatServerClientInit } from './WechatServerClient'; 6 | -------------------------------------------------------------------------------- /packages/wener-client/src/wechat/webhook/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './types'; 2 | export * from './WechatWebhookHandler'; 3 | export * from './crypt'; 4 | -------------------------------------------------------------------------------- /packages/wener-client/src/wecom/archive/bun/index.ts: -------------------------------------------------------------------------------- 1 | export * from './WeWorkFinanceClient'; 2 | -------------------------------------------------------------------------------- /packages/wener-client/src/wecom/archive/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './types'; 2 | export { MessageType, MessageAction } from './enum'; 3 | 4 | export { collectSdkFiles, type CollectSdkFileItem } from './utils/collectSdkFiles'; 5 | export { normalizeMessageTypeContent } from './utils/normalizeMessageTypeContent'; 6 | export { parseChatRecordMessageItem } from './utils/parseChatRecordMessageItem'; 7 | export { parseMixedMessageItem } from './utils/parseMixedMessageItem'; 8 | -------------------------------------------------------------------------------- /packages/wener-client/src/wecom/archive/server/index.ts: -------------------------------------------------------------------------------- 1 | export { decryptRandomKey } from './decryptRandomKey'; 2 | -------------------------------------------------------------------------------- /packages/wener-client/src/wecom/archive/utils/parseMixedMessageItem.ts: -------------------------------------------------------------------------------- 1 | import type { MixedMessageItem, ParsedMixedMessageItem } from '../types'; 2 | 3 | export function parseMixedMessageItem(v: MixedMessageItem | ParsedMixedMessageItem): ParsedMixedMessageItem { 4 | const { type, content } = v; 5 | return { 6 | type, 7 | content: typeof content === 'string' ? JSON.parse(content) : content, 8 | } as any; 9 | } 10 | -------------------------------------------------------------------------------- /packages/wener-client/src/wecom/buildUrl.ts: -------------------------------------------------------------------------------- 1 | import { buildAuthorizeUrl as _buildAuthorizeUrl, type BuildAuthorizeUrlOptions } from '../wechat/buildUrl'; 2 | 3 | export function buildAuthorizeUrl( 4 | o: BuildAuthorizeUrlOptions & { 5 | scope?: 'snsapi_base' | 'snsapi_privateinfo' | 'snsapi_userinfo'; 6 | agentid?: string; // 工作台、聊天工具栏、应用会话内发起oauth2请求的场景中,会触发接口许可的自动激活 7 | }, 8 | ) { 9 | return _buildAuthorizeUrl(o); 10 | } 11 | -------------------------------------------------------------------------------- /packages/wener-client/src/wecom/getWecomJsSdk.ts: -------------------------------------------------------------------------------- 1 | export type WecomSdk = typeof import('@wecom/jssdk'); 2 | 3 | export function getWecomJsSdk() { 4 | return globalThis.window?.ww; 5 | } 6 | 7 | declare global { 8 | interface Window { 9 | ww: WecomSdk; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/wener-client/src/wecom/index.ts: -------------------------------------------------------------------------------- 1 | export { getWecomJsSdk, type WecomSdk } from './getWecomJsSdk'; 2 | export { isWecomUserAgent } from './useragent'; 3 | export { buildAppInstallUrl } from './buildProviderUrl'; 4 | export { buildAuthorizeUrl } from './buildUrl'; 5 | -------------------------------------------------------------------------------- /packages/wener-client/src/wecom/server/index.ts: -------------------------------------------------------------------------------- 1 | export * from './WecomCorpClient'; 2 | export * from './request'; 3 | export * from './WecomConfig'; 4 | export * from './api'; 5 | export * from './webhook'; 6 | export type * from './types'; 7 | -------------------------------------------------------------------------------- /packages/wener-client/src/wecom/useragent.ts: -------------------------------------------------------------------------------- 1 | import { getGlobalThis } from '@wener/utils'; 2 | 3 | export function isWecomUserAgent(userAgent = getGlobalThis().navigator?.userAgent || '') { 4 | return userAgent?.includes('wxwork'); 5 | } 6 | -------------------------------------------------------------------------------- /packages/wener-client/src/wecom/webhook/crypto.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/packages/wener-client/src/wecom/webhook/crypto.ts -------------------------------------------------------------------------------- /packages/wener-client/src/wecom/webhook/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './types'; 2 | -------------------------------------------------------------------------------- /packages/wener-client/src/xunfei/index.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /packages/wener-client/src/xunfei/spark/index.ts: -------------------------------------------------------------------------------- 1 | export { XunfeiSparkClient, type ClientOptions, type ClientOptionsInit } from './XunfeiSparkClient'; 2 | export * from './XunfeiConfig'; 3 | -------------------------------------------------------------------------------- /packages/wener-client/src/yzf/errors.ts: -------------------------------------------------------------------------------- 1 | export class UnauthenticatedError extends Error {} 2 | -------------------------------------------------------------------------------- /packages/wener-client/src/yzf/index.ts: -------------------------------------------------------------------------------- 1 | export { Client, type ClientOptions, type ClientOptionsInit } from './Client'; 2 | export { request, type RequestOptions, type Token, type TokenProvider } from './request'; 3 | export type * from './types'; 4 | export { ping, createRefreshableTokenProvider, getTokenPayload, getTokenExpiresAt, type TokenPayload } from './token'; 5 | export { UnauthenticatedError } from './errors'; 6 | export { decrypt } from './decrypt'; 7 | -------------------------------------------------------------------------------- /packages/wener-common/.prettierignore: -------------------------------------------------------------------------------- 1 | parser.js 2 | -------------------------------------------------------------------------------- /packages/wener-common/src/cn/__snapshots__/ResidentIdentityCardNumber.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`ResidentIdentityCardNumber > should parse 1`] = ` 4 | { 5 | "age": 75, 6 | "birthDate": "19491231", 7 | "checksum": "X", 8 | "division": "110105", 9 | "female": true, 10 | "male": false, 11 | "sequence": 2, 12 | "sex": "Female", 13 | "valid": true, 14 | } 15 | `; 16 | -------------------------------------------------------------------------------- /packages/wener-common/src/cn/formatDate.ts: -------------------------------------------------------------------------------- 1 | export function formatDate(date: Date, format: 'yyyyMMDD') { 2 | switch (format) { 3 | case 'yyyyMMDD': { 4 | const year = date.getFullYear(); 5 | const month = (date.getMonth() + 1).toString().padStart(2, '0'); 6 | const day = date.getDate().toString().padStart(2, '0'); 7 | return `${year}${month}${day}`; 8 | } 9 | default: 10 | throw new Error(`Invalid format`); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/wener-common/src/cn/index.ts: -------------------------------------------------------------------------------- 1 | export { ResidentIdentityCardNumber } from './ResidentIdentityCardNumber'; 2 | export { DivisionCode } from './DivisionCode'; 3 | export { UnifiedSocialCreditCode } from './UnifiedSocialCreditCode'; 4 | -------------------------------------------------------------------------------- /packages/wener-common/src/index.ts: -------------------------------------------------------------------------------- 1 | export { normalizePagination } from './normalizePagination'; 2 | export { parseSort, type SortRule } from './parseSort'; 3 | -------------------------------------------------------------------------------- /packages/wener-common/src/jsonschema/index.ts: -------------------------------------------------------------------------------- 1 | export { JsonSchema } from './JsonSchema'; 2 | export type { JsonSchemaDef } from './types'; 3 | -------------------------------------------------------------------------------- /packages/wener-common/src/meta/defineMetadata.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from 'vitest'; 2 | import { createMetadataKey, defineMetadata, getMetadata } from './defineMetadata'; 3 | 4 | test('defineMetadata', () => { 5 | const key = createMetadataKey('name'); 6 | 7 | const user = { 8 | metadata: {}, 9 | }; 10 | 11 | defineMetadata(user, key, 'wener'); 12 | 13 | expect(user.metadata).toEqual({ name: 'wener' }); 14 | expect(getMetadata(user, key)).toEqual('wener'); 15 | }); 16 | -------------------------------------------------------------------------------- /packages/wener-common/src/meta/index.ts: -------------------------------------------------------------------------------- 1 | export { createMetadataKey, defineMetadata, getMetadata } from './defineMetadata'; 2 | 3 | export { defineInit, type InitDef, runInit } from './defineInit'; 4 | 5 | export { defineFileType, getFileType, type FileTypeDef } from './defineFileType'; 6 | -------------------------------------------------------------------------------- /packages/wener-common/src/password/index.ts: -------------------------------------------------------------------------------- 1 | export { PHC } from './PHC'; 2 | export { Password } from './Password'; 3 | export { createArgon2PasswordAlgorithm } from './createArgon2PasswordAlgorithm'; 4 | export { createBase64PasswordAlgorithm } from './createBase64PasswordAlgorithm'; 5 | export { createBcryptPasswordAlgorithm } from './createBcryptPasswordAlgorithm'; 6 | -------------------------------------------------------------------------------- /packages/wener-common/src/password/server/index.ts: -------------------------------------------------------------------------------- 1 | export { createScryptPasswordAlgorithm } from '../createScryptPasswordAlgorithm'; 2 | -------------------------------------------------------------------------------- /packages/wener-common/src/search/Makefile: -------------------------------------------------------------------------------- 1 | gen: 2 | pnpm dlx peggy@latest $(PWD)/parser.peggy --format es 3 | -------------------------------------------------------------------------------- /packages/wener-common/src/search/index.ts: -------------------------------------------------------------------------------- 1 | export { AdvanceSearch } from './AdvanceSearch'; 2 | -------------------------------------------------------------------------------- /packages/wener-common/src/search/parser.d.ts: -------------------------------------------------------------------------------- 1 | export function parse(input: string, options?: ParseOptions): any; 2 | 3 | export interface ParseOptions { 4 | grammarSource?: string; 5 | startRule?: string; 6 | 7 | [k: string]: any; 8 | } 9 | -------------------------------------------------------------------------------- /packages/wener-common/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config'; 2 | 3 | export default defineConfig({ 4 | test: { 5 | alias: { 6 | '@/': new URL('./src/', import.meta.url).pathname, 7 | }, 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /packages/wener-console/.prettierignore: -------------------------------------------------------------------------------- 1 | .next 2 | src/buildinfo 3 | dist 4 | node_modules 5 | ignored 6 | -------------------------------------------------------------------------------- /packages/wener-console/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /packages/wener-console/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | 'tailwindcss/nesting': {}, 4 | tailwindcss: {}, 5 | autoprefixer: {}, 6 | ...(process.env.NODE_ENV === 'production' ? { cssnano: {} } : {}), 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /packages/wener-console/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /api/ 3 | -------------------------------------------------------------------------------- /packages/wener-console/src/assets/LoginSplash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/packages/wener-console/src/assets/LoginSplash.jpg -------------------------------------------------------------------------------- /packages/wener-console/src/buildinfo/index.ts: -------------------------------------------------------------------------------- 1 | export { getBuildInfo, type BuildInfo } from './getBuildInfo'; 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/client/graphql/getUrqlClient.ts: -------------------------------------------------------------------------------- 1 | import type { Client } from '@urql/core'; 2 | import { getGlobalStates } from '@wener/utils'; 3 | import { getAccessToken } from '../../console/context'; 4 | import { createUrqlClient } from '../../urql'; 5 | import { getGraphQLUrl } from './getGraphQLUrl'; 6 | 7 | export function getUrqlClient(): Client { 8 | return getGlobalStates('UrqlClient', () => 9 | createUrqlClient({ 10 | getToken: getAccessToken, 11 | url: getGraphQLUrl(), 12 | }), 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /packages/wener-console/src/client/graphql/index.ts: -------------------------------------------------------------------------------- 1 | export { gqlr } from './gqlr'; 2 | export { getUrqlClient } from './getUrqlClient'; 3 | export { getGraphQLUrl } from './getGraphQLUrl'; 4 | -------------------------------------------------------------------------------- /packages/wener-console/src/components/DevOnly.tsx: -------------------------------------------------------------------------------- 1 | import type { FC, ReactNode } from 'react'; 2 | import React from 'react'; 3 | 4 | export const DevOnly: FC<{ children?: ReactNode; fallback?: ReactNode }> = ({ children, fallback = null }) => { 5 | const dev = process.env.NODE_ENV === 'development'; 6 | return dev ? <>{children} : fallback; 7 | }; 8 | -------------------------------------------------------------------------------- /packages/wener-console/src/components/WebVitals.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useReportWebVitals } from './useReportWebVitals'; 4 | 5 | export function WebVitals() { 6 | useReportWebVitals((metric) => { 7 | console.log(metric); 8 | }); 9 | return null; 10 | } 11 | -------------------------------------------------------------------------------- /packages/wener-console/src/console/ConsoleLauncher/ConsoleLauncher.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/packages/wener-console/src/console/ConsoleLauncher/ConsoleLauncher.tsx -------------------------------------------------------------------------------- /packages/wener-console/src/console/ConsoleLauncher/LauncherStore.tsx: -------------------------------------------------------------------------------- 1 | import { Launcher, type LauncherItem } from './Launcher'; 2 | 3 | /** 4 | * @deprecated use {@link Launcher.toggle} instead 5 | */ 6 | export function toggleLauncher(open?: boolean) { 7 | Launcher.toggle(open); 8 | } 9 | 10 | /** 11 | * @deprecated use {@link Launcher.addItems} instead 12 | */ 13 | export function addLaunchItems(items: LauncherItem[]) { 14 | Launcher.addItems(items); 15 | } 16 | -------------------------------------------------------------------------------- /packages/wener-console/src/console/ConsoleLauncher/index.ts: -------------------------------------------------------------------------------- 1 | export { toggleLauncher, addLaunchItems } from './LauncherStore'; 2 | export { Launcher } from './Launcher'; 3 | export { ConsoleLauncher } from './Launcher'; 4 | export type { ConsoleLauncherProps } from './Launcher'; 5 | -------------------------------------------------------------------------------- /packages/wener-console/src/console/applets/Clock/Clock.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { Meta } from '@storybook/react'; 3 | import { Clock } from './Clock'; 4 | 5 | const meta: Meta = { 6 | title: 'console/applet/Clock', 7 | parameters: { 8 | layout: 'fullscreen', 9 | }, 10 | }; 11 | export default meta; 12 | 13 | export const Demo = () => { 14 | return ; 15 | }; 16 | -------------------------------------------------------------------------------- /packages/wener-console/src/console/applets/index.ts: -------------------------------------------------------------------------------- 1 | export { ClockWidget } from './ClockWidget'; 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/console/components/ConsoleLayout/index.ts: -------------------------------------------------------------------------------- 1 | export { ConsoleLayout } from './ConsoleLayout'; 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/console/components/DockLayout/index.ts: -------------------------------------------------------------------------------- 1 | export { DockLayout } from './DockLayout'; 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/console/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ConsoleComponent'; 2 | export { StaticRootReactor } from './StaticRootReactor'; 3 | export { ModuleMainLayout } from './ModuleMainLayout'; 4 | -------------------------------------------------------------------------------- /packages/wener-console/src/console/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export { useUserPreferenceState } from './useUserPreferenceState'; 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/console/pages/LoginPage/index.ts: -------------------------------------------------------------------------------- 1 | export { type LoginFormData, type LoginPageProps, LoginPage } from './LoginPage'; 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/console/pages/SystemAboutPage/index.ts: -------------------------------------------------------------------------------- 1 | export { SystemAboutPage } from './SystemAboutPage'; 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/console/pages/index.ts: -------------------------------------------------------------------------------- 1 | export { SystemAboutPage } from './SystemAboutPage'; 2 | export { AppearanceSettingPage } from './AppearanceSettingPage/AppearanceSettingPage'; 3 | export { LoginPage, type LoginFormData, type LoginPageProps } from './LoginPage'; 4 | -------------------------------------------------------------------------------- /packages/wener-console/src/console/user/index.ts: -------------------------------------------------------------------------------- 1 | export { getUserAction } from './getUserAction'; 2 | export { UserAuthExpireOverlay } from './UserAuthExpireOverlay'; 3 | export { UserLockOverlay } from './UserLockOverlay'; 4 | export { UserLoader } from './UserLoader'; 5 | -------------------------------------------------------------------------------- /packages/wener-console/src/daisy/const.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-redeclare */ 2 | import { z } from 'zod'; 3 | 4 | export const SizeType = z.enum(['lg', 'md', 'sm', 'xs'] as const); 5 | export type SizeType = z.infer; 6 | 7 | export const IntentType = z.enum(['primary', 'secondary', 'accent', 'info', 'success', 'warning', 'error'] as const); 8 | export type IntentType = z.infer; 9 | -------------------------------------------------------------------------------- /packages/wener-console/src/daisy/isNodeTypeOf.tsx: -------------------------------------------------------------------------------- 1 | import React, { type JSXElementConstructor, type ReactElement, type ReactNode } from 'react'; 2 | import { arrayOfMaybeArray, type MaybeArray } from '@wener/utils'; 3 | 4 | export function isNodeTypeOf( 5 | ele: ReactNode, 6 | component: MaybeArray>, 7 | ): ele is ReactElement { 8 | return React.isValidElement(ele) && arrayOfMaybeArray(component).includes(ele.type as any); 9 | } 10 | -------------------------------------------------------------------------------- /packages/wener-console/src/daisy/theme/getTheme.tsx: -------------------------------------------------------------------------------- 1 | export function getTheme(): string { 2 | if (typeof window === 'undefined') { 3 | return 'system'; 4 | } 5 | return localStorage.theme || 'system'; 6 | } 7 | -------------------------------------------------------------------------------- /packages/wener-console/src/daisy/theme/index.ts: -------------------------------------------------------------------------------- 1 | export { DaisyThemeDemo } from './DaisyThemeDemo'; 2 | export { ThemeSelectorButton } from './ThemeSelectorButton'; 3 | export { ThemeListSelector } from './ThemeListSelector'; 4 | export { getSupportedThemes } from './getSupportedThemes'; 5 | export { getPrefersColorSchema } from '../../utils/getPrefersColorSchema'; 6 | 7 | export { DaisyTheme } from './DaisyTheme'; 8 | -------------------------------------------------------------------------------- /packages/wener-console/src/daisy/theme/setElementThemeAttribute.tsx: -------------------------------------------------------------------------------- 1 | export function setElementThemeAttribute( 2 | theme: string | undefined, 3 | el = typeof document === 'undefined' ? undefined : document.documentElement, 4 | ) { 5 | if (!theme || !el) { 6 | return; 7 | } 8 | el.setAttribute('data-theme', theme); 9 | } 10 | -------------------------------------------------------------------------------- /packages/wener-console/src/floating/index.ts: -------------------------------------------------------------------------------- 1 | export { useFloatingInteractions, type UseFloatingInteractionsOptions } from './useFloatingInteractions'; 2 | export { Popover, type PopoverProps, type PopoverContentProps } from './Popover'; 3 | export { Tooltip, type TooltipProps } from './Tooltip'; 4 | export { usePopover } from './usePopover'; 5 | -------------------------------------------------------------------------------- /packages/wener-console/src/foundation/auth/index.ts: -------------------------------------------------------------------------------- 1 | export { AuthReady } from './AuthReady'; 2 | export { AuthBlock } from './AuthBlock'; 3 | export { AuthSidecar, getAuthState, getAuthStore } from './AuthStore'; 4 | -------------------------------------------------------------------------------- /packages/wener-console/src/foundation/site/index.ts: -------------------------------------------------------------------------------- 1 | export { SiteLoader } from './SiteLoader'; 2 | export { SiteSidecar } from './SiteSidecar'; 3 | export { type SiteStore } from './SiteStore'; 4 | -------------------------------------------------------------------------------- /packages/wener-console/src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useExposeDebug'; 2 | export * from './useLogger'; 3 | export * from './useContextStore'; 4 | -------------------------------------------------------------------------------- /packages/wener-console/src/hooks/useExposeDebug.ts: -------------------------------------------------------------------------------- 1 | const __DEV__ = process.env.NODE_ENV === 'development'; 2 | 3 | export function useExposeDebug(o: Record) { 4 | if (__DEV__) { 5 | if (typeof window !== 'undefined') { 6 | const debug = ((window as any).__DEBUG_HOLDER__ ||= {}); 7 | Object.assign(debug, o); 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/wener-console/src/icons/svg/brands/DingtalkBrandIcon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/wener-console/src/jsonschema/index.ts: -------------------------------------------------------------------------------- 1 | export { JsonSchema } from '@wener/common/jsonschema'; 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/loader/README.md: -------------------------------------------------------------------------------- 1 | Cube Flipping Loader 2 | https://codepen.io/nikhil8krishnan/pen/dMEzGx 3 | 4 | Collection 5 | https://codepen.io/collection/jifIK 6 | 7 | Sun moon 8 | https://codepen.io/ccromjongh/pen/yemQEQ 9 | 10 | Smiling 11 | https://codepen.io/balapa/pen/VvVebO 12 | 13 | full tint 14 | https://codepen.io/Keale2/pen/mJzzNr 15 | 16 | simple line 17 | https://codepen.io/bernethe/pen/dorozd 18 | 19 | Windows & MacOS System Loader 20 | https://codepen.io/semajtwin/pen/EagrQV 21 | -------------------------------------------------------------------------------- /packages/wener-console/src/loader/index.ts: -------------------------------------------------------------------------------- 1 | export { DotsFadeLoader } from './DotsFadeLoader/DotsFadeLoader'; 2 | export { LoadingIndicator } from './LoadingIndicator'; 3 | -------------------------------------------------------------------------------- /packages/wener-console/src/matomo/index.ts: -------------------------------------------------------------------------------- 1 | export { MatomoTracker } from './MatomoTracker'; 2 | export { getTracker } from './MatomoTrackerStore'; 3 | -------------------------------------------------------------------------------- /packages/wener-console/src/meta/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @deprecated 3 | */ 4 | export { createMetadataKey, defineMetadata, getMetadata } from '@wener/common/meta'; 5 | -------------------------------------------------------------------------------- /packages/wener-console/src/react-hook-form/index.ts: -------------------------------------------------------------------------------- 1 | export { ReactHookForm } from './ReactHookForm'; 2 | export { getDirtyFields } from './getDirtyFields'; 3 | export { getFieldErrors } from './getFieldErrors'; 4 | -------------------------------------------------------------------------------- /packages/wener-console/src/toast/TODO.ts: -------------------------------------------------------------------------------- 1 | import { toast } from 'react-hot-toast'; 2 | import { warn } from './warn'; 3 | 4 | export function TODO(msg = 'TODO') { 5 | // once 6 | warn(msg) || toast.success(`TODO: ${msg}`); 7 | } 8 | -------------------------------------------------------------------------------- /packages/wener-console/src/toast/index.ts: -------------------------------------------------------------------------------- 1 | export { TODO } from './TODO'; 2 | export { showErrorToast } from './showErrorToast'; 3 | export { showSuccessToast } from './showSuccessToast'; 4 | export { showPromiseToast } from './showPromiseToast'; 5 | export { resolveErrorMessage } from './resolveErrorMessage'; 6 | -------------------------------------------------------------------------------- /packages/wener-console/src/toast/showErrorToast.tsx: -------------------------------------------------------------------------------- 1 | import { toast } from 'react-hot-toast'; 2 | import { classOf } from '@wener/utils'; 3 | import { resolveErrorMessage } from './resolveErrorMessage'; 4 | 5 | export function showErrorToast(error: Error | any) { 6 | if (!error) { 7 | return; 8 | } 9 | // window.__LAST_ERROR__ = error; 10 | console.log(`ERROR ${classOf(error)}`, error); 11 | toast.error(resolveErrorMessage(error)); 12 | } 13 | -------------------------------------------------------------------------------- /packages/wener-console/src/toast/showSuccessToast.tsx: -------------------------------------------------------------------------------- 1 | import { toast, type Renderable } from 'react-hot-toast'; 2 | import { warn } from './warn'; 3 | 4 | export function showSuccessToast(msg: Renderable | { message: string }) { 5 | let c: Renderable = msg && typeof msg === 'object' && 'message' in msg ? msg.message : msg; 6 | if (!c) { 7 | warn('showSuccessToast: msg is empty'); 8 | } 9 | c ||= '成功!'; 10 | toast.success(c); 11 | } 12 | -------------------------------------------------------------------------------- /packages/wener-console/src/toast/warn.ts: -------------------------------------------------------------------------------- 1 | let counter: Record; 2 | 3 | export function warn(msg: string, ...args: any[]) { 4 | if (!counter) { 5 | counter = {}; 6 | } 7 | counter[msg] = counter[msg] || 0; 8 | let count = counter[msg]++; 9 | if (count === 0) { 10 | console.trace(`[WARN] ${count}: ${msg}`, ...args); 11 | } else { 12 | console.warn(`[WARN] ${count}: ${msg}`, ...args); 13 | } 14 | return count; 15 | } 16 | -------------------------------------------------------------------------------- /packages/wener-console/src/tw/cn.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, test } from 'vitest'; 2 | import { cn } from './cn'; 3 | 4 | describe('cn', () => { 5 | test('should merge class', () => { 6 | expect(cn('p-1 p-2')).toBe('p-2'); 7 | }); 8 | 9 | test('should merge daisy ui', () => { 10 | expect(cn('btn-info btn-xs btn-sm btn-md', 'btn-success')).toBe('btn-md btn-success'); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /packages/wener-console/src/tw/index.ts: -------------------------------------------------------------------------------- 1 | export { cn } from './cn'; 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/types.ts: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react'; 2 | 3 | export interface NextPageProps

, S = Record> { 4 | params: P; 5 | searchParams: S; 6 | } 7 | 8 | export interface NextLayoutProps

> { 9 | params: P; 10 | children?: ReactNode; 11 | } 12 | 13 | declare module 'react' { 14 | interface CSSProperties { 15 | // var or prefix 16 | [key: `-${string}`]: string | number; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/wener-console/src/urql/index.ts: -------------------------------------------------------------------------------- 1 | export { createUrqlClient } from './createUrqlClient'; 2 | export { batchFetchExchange } from './batchFetchExchange'; 3 | -------------------------------------------------------------------------------- /packages/wener-console/src/utils/getPrefersColorSchema.tsx: -------------------------------------------------------------------------------- 1 | export function getPrefersColorSchema(): 'dark' | 'light' { 2 | if (typeof window === 'undefined') { 3 | return 'light'; 4 | } 5 | return window?.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; 6 | } 7 | -------------------------------------------------------------------------------- /packages/wener-console/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/components/ErrorSuspenseBoundary/index.ts: -------------------------------------------------------------------------------- 1 | export { ErrorSuspenseBoundary } from './ErrorSuspenseBoundary'; 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/components/ImagePreview/index.ts: -------------------------------------------------------------------------------- 1 | export { ImagePreview, type ImagePreviewProps, useImagePreviewContext } from './ImagePreview'; 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/components/UpdateNotification/index.ts: -------------------------------------------------------------------------------- 1 | export { UpdateNotification } from './UpdateNotification'; 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/hooks/env.tsx: -------------------------------------------------------------------------------- 1 | export function useIsDev() { 2 | return process.env.NODE_ENV === 'development'; 3 | } 4 | 5 | export function useIsProd() { 6 | return !useIsDev(); 7 | } 8 | 9 | export function useIsClient() { 10 | return typeof window !== 'undefined' && typeof location !== 'undefined'; 11 | } 12 | 13 | let _isNextJS: boolean | undefined; 14 | 15 | export function useIsNextJS() { 16 | return (_isNextJS ||= Boolean((globalThis as any).next?.version)); 17 | } 18 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export { useLocalStorageState } from './useLocalStorageState'; 2 | export { useIsNextJS, useIsClient, useIsDev, useIsProd } from './env'; 3 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/layouts/ExpandableSideMenuLayout/BaseNavLink.tsx: -------------------------------------------------------------------------------- 1 | import type { ComponentType, ReactElement } from 'react'; 2 | 3 | export type BaseNavLink = ComponentType; 4 | 5 | export interface BaseNavLinkProps extends Record { 6 | href: string; 7 | children: ReactElement | ((o: { isActive: boolean }) => ReactElement); 8 | className: string | ((o: { isActive: boolean }) => string); 9 | } 10 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/layouts/LeftSideMenuBarLayout/index.ts: -------------------------------------------------------------------------------- 1 | export { LeftSideMenuBarLayout } from './LeftSideMenuBarLayout'; 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/links/BaseNavLink.tsx: -------------------------------------------------------------------------------- 1 | import type { ComponentType, ReactElement } from 'react'; 2 | 3 | export type BaseNavLink = ComponentType; 4 | 5 | export interface BaseNavLinkProps extends Record { 6 | children: ReactElement | ((o: { isActive: boolean }) => ReactElement); 7 | className: string | ((o: { isActive: boolean }) => string); 8 | } 9 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/links/index.ts: -------------------------------------------------------------------------------- 1 | // export { ActiveLink, type ActiveLinkProps } from './ActiveLink'; 2 | // export { NextNavLink, type NextNavLinkProps } from './NextNavLink'; 3 | export { AutoNavLink, ReactRouterNavLink, type AutoNavLinkProps } from './AutoNavLink'; 4 | export type { BaseNavLink, BaseNavLinkProps } from './BaseNavLink'; 5 | export { StaticNavLink } from './StaticNavLink'; 6 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/module/DynamicStore.test.ts: -------------------------------------------------------------------------------- 1 | import { assert, test } from 'vitest'; 2 | import { DynamicStore } from './DynamicStore'; 3 | import type { ModuleStore } from './types'; 4 | 5 | test('DynamicStore', () => { 6 | let store: ModuleStore = new DynamicStore(); 7 | { 8 | const s = store.as(); 9 | s.add('a.b', '1'); 10 | s.add('a.b', ['2']); 11 | assert.deepEqual(s.collect('a.b'), ['1', '2']); 12 | } 13 | }); 14 | 15 | interface Val { 16 | a: { 17 | b: string[]; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/pages/index.ts: -------------------------------------------------------------------------------- 1 | export { LoginPage, type LoginFormData } from '../../console/pages/LoginPage/LoginPage'; 2 | export { SystemAboutPage } from '../../console/pages/SystemAboutPage/SystemAboutPage'; 3 | // export { DevDebugPage } from '../../demo/pages/DevDebugPage'; 4 | export { AppearanceSettingPage } from '../../console/pages/AppearanceSettingPage/AppearanceSettingPage'; 5 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/prefs.ts: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react'; 2 | 3 | export interface SitePreferences { 4 | site: { 5 | title: string; 6 | logo: ReactNode; 7 | author: { 8 | name: string; 9 | link: string; 10 | }; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/resource/index.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/site/SiteLogo.tsx: -------------------------------------------------------------------------------- 1 | import { GrSystem } from 'react-icons/gr'; 2 | import { flexRender } from '@wener/reaction'; 3 | import { useContextStore } from '../../hooks'; 4 | import type { SitePreferences } from '../prefs'; 5 | 6 | export const SiteLogo = (props: any) => { 7 | const { useWatch } = useContextStore(); 8 | const logo = useWatch('site.logo'); 9 | return flexRender(logo || GrSystem, props, true); 10 | }; 11 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/utils/index.ts: -------------------------------------------------------------------------------- 1 | export { getPrefersColorSchema } from '../../utils/getPrefersColorSchema'; 2 | -------------------------------------------------------------------------------- /packages/wener-console/src/web/window/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @deprecated use `@wener/console/window` instead 3 | */ 4 | export * from '../../window'; 5 | -------------------------------------------------------------------------------- /packages/wener-console/src/window/WindowHost.tsx: -------------------------------------------------------------------------------- 1 | import { Window } from './Window'; 2 | 3 | export const WindowHost = Window.Host; 4 | -------------------------------------------------------------------------------- /packages/wener-console/src/window/const.ts: -------------------------------------------------------------------------------- 1 | export function getWindowDragHandleClassname() { 2 | return 'WindowDragHandle'; 3 | } 4 | 5 | export function getWindowDragCancelClassname() { 6 | return 'WindowDragCancel'; 7 | } 8 | -------------------------------------------------------------------------------- /packages/wener-console/src/window/index.ts: -------------------------------------------------------------------------------- 1 | export { getWindowDragHandleClassname, getWindowDragCancelClassname } from './const'; 2 | export { ReactWindow, getRootWindow, useWindow, type WindowOpenOptions } from './ReactWindow'; 3 | export { WindowHost } from './WindowHost'; 4 | export { WindowGuest } from './WindowGuest'; 5 | export { Window } from './Window'; 6 | -------------------------------------------------------------------------------- /packages/wener-console/src/window/windows/Windows.module.css: -------------------------------------------------------------------------------- 1 | .WindowController { 2 | @apply flex h-full; 3 | 4 | & > button { 5 | @apply flex items-center justify-center; 6 | width: 42px; 7 | 8 | &[data-action="close"]:hover { 9 | @apply bg-error; 10 | } 11 | 12 | &:hover { 13 | @apply bg-base-300; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/wener-console/src/zustand/index.ts: -------------------------------------------------------------------------------- 1 | export { createStoreContext } from './createStoreContext'; 2 | export { createStoreSelectorHook } from './createStoreSelectorHook'; 3 | -------------------------------------------------------------------------------- /packages/wener-console/svgo.config.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: [ 3 | 'preset-default', 4 | { 5 | name: 'removeAttrs', 6 | params: { 7 | attrs: ['data-.*'], 8 | }, 9 | }, 10 | { 11 | name: 'sortAttrs', 12 | }, 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /packages/wener-miniquery/.gitognore: -------------------------------------------------------------------------------- 1 | miniquery.js.map 2 | -------------------------------------------------------------------------------- /packages/wener-miniquery/.prettierignore: -------------------------------------------------------------------------------- 1 | miniquery.js 2 | -------------------------------------------------------------------------------- /packages/wener-miniquery/.swcrc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/swcrc", 3 | "sourceMaps": true, 4 | "module": { 5 | "type": "es6" 6 | }, 7 | "jsc": { 8 | "target": "es2017", 9 | "parser": { 10 | "syntax": "typescript", 11 | "decorators": true, 12 | "dynamicImport": true 13 | }, 14 | "transform": { 15 | "legacyDecorator": true, 16 | "decoratorMetadata": true 17 | }, 18 | "keepClassNames": true 19 | }, 20 | "minify": false 21 | } 22 | -------------------------------------------------------------------------------- /packages/wener-miniquery/Makefile: -------------------------------------------------------------------------------- 1 | REPO_ROOT ?= $(shell git rev-parse --show-toplevel) 2 | -include $(REPO_ROOT)/base.mk 3 | 4 | build: 5 | # $(NDEV) build lib 6 | -rm -rf lib/* 7 | pnpm swc ./src -d ./lib --strip-leading-paths --copy-files 8 | npx -y ts-add-js-extension --dir=lib 9 | 10 | publish: build 11 | pnpm version patch --no-workspaces-update 12 | pnpm publish --registry https://registry.npmjs.org --access public --no-git-checks 13 | -------------------------------------------------------------------------------- /packages/wener-miniquery/README.md: -------------------------------------------------------------------------------- 1 | - [MiniQuery](https://wener.me/notes/languages/miniquery) 2 | 3 | SQL Where like **safe** filter expression for ORM. 4 | 5 | ## See also 6 | -------------------------------------------------------------------------------- /packages/wener-miniquery/src/index.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /packages/wener-miniquery/src/mikro-orm/Makefile: -------------------------------------------------------------------------------- 1 | gen: 2 | npx -y peggy $(PWD)/parser.pegjs --format es 3 | #npx prettier -w $(PWD)/miniquery.js # .js.map 失效 4 | -------------------------------------------------------------------------------- /packages/wener-miniquery/src/mikro-orm/index.ts: -------------------------------------------------------------------------------- 1 | export { toMikroOrmQuery } from './toMikroOrmQuery'; 2 | -------------------------------------------------------------------------------- /packages/wener-miniquery/src/mikro-orm/parser.d.ts: -------------------------------------------------------------------------------- 1 | export function parse(input: string, options?: ParseOptions): any; 2 | 3 | export interface ParseOptions { 4 | grammarSource?: string; 5 | startRule?: string; 6 | 7 | [k: string]: any; 8 | } 9 | -------------------------------------------------------------------------------- /packages/wener-miniquery/src/ohm/ast.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from 'vitest'; 2 | import { toMiniQueryAST } from './ast'; 3 | 4 | test('miniquery ast', () => { 5 | for (const v of [`a > -1`]) { 6 | const ast = toMiniQueryAST(v); 7 | expect(ast).toBeTruthy(); 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /packages/wener-miniquery/src/ohm/grammar/index.ts: -------------------------------------------------------------------------------- 1 | import grammar from './miniquery.ohm-bundle'; 2 | 3 | export { default as MiniQueryGrammar } from './miniquery.ohm-bundle'; 4 | export default grammar; 5 | export const semantics = grammar.createSemantics(); 6 | export const MiniQuerySemantics = semantics; 7 | -------------------------------------------------------------------------------- /packages/wener-miniquery/src/ohm/index.ts: -------------------------------------------------------------------------------- 1 | export * from './grammar'; 2 | export { toMiniQueryAST, getMiniQueryASTOp, type MiniQueryASTNode } from './ast'; 3 | -------------------------------------------------------------------------------- /packages/wener-miniquery/src/ohm/sequelize/index.ts: -------------------------------------------------------------------------------- 1 | export { toSequelizeWhere, type SequelizeWhereOptions } from './where'; 2 | -------------------------------------------------------------------------------- /packages/wener-miniquery/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "moduleResolution": "bundler", 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "verbatimModuleSyntax": true, 9 | "strict": true 10 | }, 11 | "include": [ 12 | "src/**/*" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/Errors.ts: -------------------------------------------------------------------------------- 1 | import { Errors as _Errors } from '@wener/utils'; 2 | 3 | /** 4 | * @deprecated use Errors from @wener/utils 5 | */ 6 | export const Errors = _Errors; 7 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/HttpStatus.ts: -------------------------------------------------------------------------------- 1 | export { getHttpStatusText } from '@wener/utils'; 2 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/actuator/const.ts: -------------------------------------------------------------------------------- 1 | export function hideActuatorApi() { 2 | return !process.env.ACTUATOR_API; 3 | } 4 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/actuator/index.ts: -------------------------------------------------------------------------------- 1 | export { ActuatorModule } from './actuator.module'; 2 | export { EnvController } from './env.controller'; 3 | export { HealthController } from './health.controller'; 4 | export { ProcessController } from './process.controller'; 5 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/app/App.test.ts: -------------------------------------------------------------------------------- 1 | import { test } from 'vitest'; 2 | import { App } from './App'; 3 | 4 | test('App', async ({}) => { 5 | console.log(`App`, JSON.stringify(App, null, 2)); 6 | }); 7 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/app/index.ts: -------------------------------------------------------------------------------- 1 | export { App } from './App'; 2 | export { 3 | Contexts, 4 | setCurrentContext, 5 | getCurrentContext, 6 | getCurrentUserId, 7 | getCurrentTenantId, 8 | getStaticTenantId, 9 | getFallbackTenantId, 10 | getCurrentFallbackTenantId, 11 | requireTenantId, 12 | } from './Contexts'; 13 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/auth/AuthPrincipal.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 用户、服务账户或机器人 3 | */ 4 | export interface AuthPrincipal { 5 | roles: string[]; 6 | 7 | [key: string]: any; 8 | } 9 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/auth/index.ts: -------------------------------------------------------------------------------- 1 | export { Role } from './role.enum'; 2 | export { Roles } from './roles.decorator'; 3 | export { type AuthPrincipal } from './AuthPrincipal'; 4 | export { Public } from './public.decorator'; 5 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/auth/public.decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from '@nestjs/common'; 2 | 3 | export const AUTH_PUBLIC_KEY = 'auth.public'; 4 | export const Public = () => SetMetadata(AUTH_PUBLIC_KEY, true); 5 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/auth/role.enum.ts: -------------------------------------------------------------------------------- 1 | export enum Role { 2 | User = 'user', 3 | Admin = 'admin', 4 | SystemAdmin = 'system-admin', 5 | } 6 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/auth/roles.decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from '@nestjs/common'; 2 | import type { Role } from './role.enum'; 3 | 4 | export const AUTH_ROLES_KEY = 'auth.roles'; 5 | export const Roles = (...roles: Role[]) => SetMetadata(AUTH_ROLES_KEY, roles); 6 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/config/config.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from 'vitest'; 2 | import { getRootConfig } from './root.config'; 3 | 4 | test('conf', () => { 5 | expect( 6 | getRootConfig({ 7 | S3_ENDPOINT: 'http://minio:9000', 8 | }), 9 | ).matchSnapshot(); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/config/index.ts: -------------------------------------------------------------------------------- 1 | export { RedisConfig, getRedisOptions, getRedisConfig } from './redis.config'; 2 | export { ServerConfig, getServerConfig } from './server.config'; 3 | export { DatabaseConfig, getDatabaseConfig, getMikroOrmConfig } from './database.config'; 4 | export { RootConfig, getRootConfig } from './root.config'; 5 | export { MinioConfig, getMinioConfig, getMinioOptions } from './minio.config'; 6 | export { NatsConfig, getNatsConfig, getNatsOptions } from './nats.config'; 7 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/decorator/cookies.decorator.ts: -------------------------------------------------------------------------------- 1 | import { createParamDecorator, type ExecutionContext } from '@nestjs/common'; 2 | 3 | export const Cookies = createParamDecorator((data: string, ctx: ExecutionContext) => { 4 | const request = ctx.switchToHttp().getRequest(); 5 | return data ? request.cookies?.[data] : request.cookies; 6 | }); 7 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/decorator/index.ts: -------------------------------------------------------------------------------- 1 | export { Cookies } from './cookies.decorator'; 2 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/entity/README.md: -------------------------------------------------------------------------------- 1 | - ORM Entity 定义 2 | - 提供常见的业务逻辑封装 3 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/entity/audit/AuditModule.ts: -------------------------------------------------------------------------------- 1 | import { MikroOrmModule } from '@mikro-orm/nestjs'; 2 | import { Module } from '@nestjs/common'; 3 | import { AuditLogEntity } from './AuditLogEntity'; 4 | import { AuditService } from './AuditService'; 5 | 6 | @Module({ 7 | imports: [MikroOrmModule.forFeature(AuditModule.Entities)], 8 | providers: [AuditService], 9 | exports: [AuditService], 10 | }) 11 | export class AuditModule { 12 | static Entities = [AuditLogEntity]; 13 | } 14 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/entity/audit/AuditService.ts: -------------------------------------------------------------------------------- 1 | import { MikroORM } from '@mikro-orm/postgresql'; 2 | import { Inject, Injectable } from '@nestjs/common'; 3 | 4 | @Injectable() 5 | export class AuditService { 6 | constructor(@Inject(MikroORM) protected readonly orm: MikroORM) {} 7 | } 8 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/entity/mixins/withVersionEntity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Property, types, type Opt } from '@mikro-orm/core'; 2 | import type { Constructor } from '@wener/utils'; 3 | 4 | export function withVersionEntity(Base: TBase) { 5 | @Entity({ abstract: true }) 6 | class HasVersionMixinEntity extends Base { 7 | @Property({ version: true, type: types.bigint, default: 0 }) 8 | version!: number & Opt; 9 | } 10 | 11 | return HasVersionMixinEntity; 12 | } 13 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/entity/service/EntityClass.ts: -------------------------------------------------------------------------------- 1 | export type EntityClass = Function & { 2 | prototype: T; 3 | 4 | StateEntity?: EntityClass; 5 | StatusEntity?: EntityClass; 6 | }; 7 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/entity/service/EntityService2.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenerme/wode/53a6ca1ccb977859aeb9cae79da816c30995c766/packages/wener-nestjs/src/entity/service/EntityService2.ts -------------------------------------------------------------------------------- /packages/wener-nestjs/src/entity/service/README.md: -------------------------------------------------------------------------------- 1 | - ORM Entity 内部服务 2 | - 封装常见业务逻辑 3 | - 按需提供额外的业务逻辑 4 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/entity/service/normalizePagination.ts: -------------------------------------------------------------------------------- 1 | export { normalizePagination } from '@wener/common'; 2 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/entity/service/parseOrder.ts: -------------------------------------------------------------------------------- 1 | export { parseSort as parseOrder, type SortRule as OrderRule } from '@wener/common'; 2 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/entity/service/resolveSearch.test.ts: -------------------------------------------------------------------------------- 1 | import { test } from 'vitest'; 2 | import { resolveSearch } from './resolveSearch'; 3 | 4 | test('resolveSearch', () => { 5 | resolveSearch('18700000000', { 6 | onKeyLike: (s) => { 7 | console.log('onKeyLike', s); 8 | }, 9 | onMobilePhone: (s) => { 10 | console.log('onMobilePhone', s); 11 | }, 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/hono/index.ts: -------------------------------------------------------------------------------- 1 | export { runServer } from './runServer'; 2 | export { serve } from './serve'; 3 | export { createHono } from './createHono'; 4 | export { createOpenAPIHono } from './createOpenAPIHono'; 5 | export { createProbeRoute } from './createProbeRoute'; 6 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/ioredis/index.ts: -------------------------------------------------------------------------------- 1 | export { parseRedisOptions } from './parseRedisOptions'; 2 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/knex/index.ts: -------------------------------------------------------------------------------- 1 | export { parseKnexUri } from './parseKnexUri'; 2 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/mikro-orm/entity/MinimalEnumBaseEntity.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntity, Entity, PrimaryKey, Property, types } from '@mikro-orm/core'; 2 | 3 | @Entity({ abstract: true }) 4 | export class MinimalEnumBaseEntity extends BaseEntity { 5 | @PrimaryKey({ type: types.string, columnType: 'text' }) 6 | value!: string; 7 | 8 | @Property({ type: types.string, columnType: 'text', nullable: true }) 9 | label?: string; 10 | } 11 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/mikro-orm/entity/MinimalTenantBaseEntity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Property, type Opt } from '@mikro-orm/core'; 2 | import { MinimalBaseEntity } from './MinimalBaseEntity'; 3 | 4 | @Entity({ abstract: true }) 5 | export abstract class MinimalTenantBaseEntity extends MinimalBaseEntity { 6 | @Property({ nullable: false, name: 'tid', defaultRaw: 'current_tenant_id()' }) 7 | tid!: string & Opt; 8 | } 9 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/modules/index.ts: -------------------------------------------------------------------------------- 1 | export { NatsModule, InjectNatsClient, NATS_CONNECTION } from '../nats/NatsModule'; 2 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/nats/index.ts: -------------------------------------------------------------------------------- 1 | export { NatsModule, InjectNatsClient, NATS_CONNECTION } from './NatsModule'; 2 | 3 | export * from './service'; 4 | 5 | export { connect } from './connect'; 6 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/nats/service/NatsServerRegistry.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class NatsServerRegistry {} 5 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/nats/service/ServerModule.ts: -------------------------------------------------------------------------------- 1 | import { ConfigurableModuleBuilder } from '@nestjs/common'; 2 | import type { NatsServiceServerModuleOptions } from './types'; 3 | 4 | export default new ConfigurableModuleBuilder() 5 | .setExtras( 6 | { 7 | isGlobal: true, 8 | }, 9 | (definition, extras) => ({ 10 | ...definition, 11 | global: extras.isGlobal, 12 | }), 13 | ) 14 | .setClassMethodName('forRoot') 15 | .build(); 16 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/nats/service/index.ts: -------------------------------------------------------------------------------- 1 | export { NatsServiceClientConnectionModule } from './NatsServiceClientConnectionModule'; 2 | export { NatsServiceServerModule } from './NatsServiceServerModule'; 3 | export type * from './types'; 4 | 5 | export { NatsServiceClientModule, type NatsServiceClientModuleOptions } from './NatsServiceClientModule'; 6 | export { handleNatsServiceRequest } from './handleNatsServiceRequest'; 7 | export { requestNatsService } from './requestNatsService'; 8 | export { addNatsService } from './addNatsService'; 9 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/nats/service/nats.ts: -------------------------------------------------------------------------------- 1 | export function getRequestSubject({ service, method }: { service: string; method: string }) { 2 | return `service.${service}.${method}`; 3 | } 4 | 5 | export function getSubscribeSubject({ service }: { service: string }) { 6 | return [ 7 | `service.${service}`, 8 | `service.${service}.*`, // for method 9 | ]; 10 | } 11 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/nats/service/types.ts: -------------------------------------------------------------------------------- 1 | import type { Msg } from 'nats'; 2 | import type { ServerMiddleware } from '../../service'; 3 | 4 | export interface NatsServiceServerModuleOptions { 5 | getServiceSubject?: (o: { service: string }) => string[]; 6 | // middlewares?: ServerMiddleware[]; 7 | queue?: string; 8 | middlewares?: ServerMiddleware[]; 9 | } 10 | 11 | export interface KnownNatsServerMetadata { 12 | NatsMsg: Msg; 13 | } 14 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/remote/README.md: -------------------------------------------------------------------------------- 1 | - 面向 RPC 场景 2 | - 请求和返回强调序列化 3 | - 支持 Partial 或 OnDemand 的查询 4 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/remote/RemoteService.ts: -------------------------------------------------------------------------------- 1 | export type RemoteService = {}; 2 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/remote/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './types'; 2 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/scripts/bundle.esbuild.ts: -------------------------------------------------------------------------------- 1 | import { bundle } from './esbuild/bundle'; 2 | 3 | const SERVER = process.env.SERVER; 4 | if (!SERVER) { 5 | throw new Error(`No server to bundle`); 6 | } 7 | 8 | await Promise.all( 9 | SERVER.split(',') 10 | .map((v) => v.trim()) 11 | .map((v) => bundle(v)), 12 | ); 13 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/scripts/esbuild/index.ts: -------------------------------------------------------------------------------- 1 | export { bundle } from './bundle'; 2 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/service/client/RemoteMethodNotImplemented.ts: -------------------------------------------------------------------------------- 1 | export class RemoteMethodNotImplemented extends Error { 2 | constructor(methodName = '') { 3 | super(`Remote method "${methodName}" not implement`); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/service/client/index.ts: -------------------------------------------------------------------------------- 1 | export { RemoteMethodNotImplemented } from './RemoteMethodNotImplemented'; 2 | export type * from './types'; 3 | export { ClientRegistry, type ClientMiddleware } from './ClientRegistry'; 4 | export { RemoteServiceOf } from './RemoteServiceOf'; 5 | export { ServiceClientModule, SERVICE_CLIENT_CONNECTION } from './ServiceClientModule'; 6 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/service/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './types'; 2 | export * from './meta'; 3 | export * from './client'; 4 | export * from './server'; 5 | export * from './schema'; 6 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/service/meta/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Service'; 2 | export * from './Method'; 3 | export { getServiceSchema, type ServiceSchema, type MethodSchema } from './getServiceSchema'; 4 | export type * from './client.types'; 5 | export type * from './server.types'; 6 | 7 | export { getServerServiceSchema } from './getServerServiceSchema'; 8 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/service/meta/server.types.ts: -------------------------------------------------------------------------------- 1 | import type { MethodOptionsInit, MethodSchema, ServiceOptions, ServiceSchema } from './index'; 2 | 3 | export type ExposeServiceOptions = ServiceOptions; 4 | export type ExposeMethodOptions = MethodOptionsInit & { 5 | expose?: boolean; 6 | }; 7 | 8 | export interface ServerServiceSchema extends ServiceSchema { 9 | name: string; 10 | options: ExposeServiceOptions; 11 | methods: MethodSchema[]; 12 | } 13 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/service/server/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | ServiceRegistry, 3 | ExposeService, 4 | ExposeMethod, 5 | EXPOSE_METHOD_METADATA_KEY, 6 | EXPOSE_SERVICE_METADATA_KEY, 7 | type ServerMiddleware, 8 | } from './ServiceRegistry'; 9 | export type * from './types'; 10 | export { createServerLoggingMiddleware } from './createServerLoggingMiddleware'; 11 | export { ServiceServerModule } from './ServiceServerModule'; 12 | export { createResponseFromRequest } from './createResponseFromRequest'; 13 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/service/utils.ts: -------------------------------------------------------------------------------- 1 | export function isValidMethodName(name: string) { 2 | if (!name) { 3 | return false; 4 | } 5 | return /^[a-z][a-z0-9_]*$/i.test(name); 6 | } 7 | 8 | export function isValidServiceName(name: string) { 9 | if (!name) { 10 | return false; 11 | } 12 | return name.split('.').every((v) => isValidMethodName(v)); 13 | } 14 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/service/wks/MetaService.ts: -------------------------------------------------------------------------------- 1 | import { RemoteMethodNotImplemented } from '../client'; 2 | import { Method, Service } from '../meta'; 3 | 4 | @Service({ 5 | name: 'wks.MetaService', 6 | }) 7 | export class MetaServiceBase { 8 | @Method({}) 9 | getSchema({ service }: { service: string }) { 10 | throw new RemoteMethodNotImplemented(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/service/wks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MetaService'; 2 | export * from './InstanceService'; 3 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/type-graphql/BaseObject.ts: -------------------------------------------------------------------------------- 1 | import { ObjectType } from 'type-graphql'; 2 | import { BaseNode } from './BaseNode'; 3 | import { RelayNode } from './relay'; 4 | 5 | @ObjectType({ implements: [RelayNode, BaseNode] }) 6 | export class BaseObject extends BaseNode {} 7 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/type-graphql/GeneralRequestInput.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLJSON } from 'graphql-scalars'; 2 | import { Field, InputType } from 'type-graphql'; 3 | import { RelayMutationInput } from './relay'; 4 | 5 | @InputType() 6 | export class GeneralRequestInput extends RelayMutationInput { 7 | @Field(() => GraphQLJSON, { nullable: true }) 8 | data?: any; 9 | } 10 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/type-graphql/JSONArgs.ts: -------------------------------------------------------------------------------- 1 | import { ArgsType, Field } from 'type-graphql'; 2 | import { GraphQLJSONScalar } from './GraphQLJSONScalar'; 3 | 4 | @ArgsType() 5 | export class JSONArgs { 6 | @Field(() => String, { nullable: true }) 7 | path?: string; 8 | 9 | @Field(() => GraphQLJSONScalar, { nullable: true }) 10 | default?: any; 11 | } 12 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/type-graphql/NestContainerType.ts: -------------------------------------------------------------------------------- 1 | import { ModuleRef } from '@nestjs/core'; 2 | import type { ContainerType, ResolverData } from 'type-graphql'; 3 | import { getContext } from '../context'; 4 | 5 | export class NestContainerType implements ContainerType { 6 | private moduleRef?: ModuleRef; 7 | 8 | get(someClass: any, resolverData: ResolverData): any | Promise { 9 | let ref = (this.moduleRef ||= getContext(ModuleRef)); 10 | return ref.get(someClass, { strict: false }); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/type-graphql/README.md: -------------------------------------------------------------------------------- 1 | - Resource 2 | - CreateResourceInput - the request input 3 | - CreateResourcePayload 4 | - ResourceCreateInput - the dto input 5 | - MutationResourceInput - the mutation input - not related to create/update 6 | - MutationResourcePayload - the mutation payload 7 | - ListQueryInput - input for some Query 8 | - ResourcePayload - the payload for query 9 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/type-graphql/entity/index.ts: -------------------------------------------------------------------------------- 1 | export { resolveNodeType } from './resolveNodeType'; 2 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/type-graphql/getObjectName.ts: -------------------------------------------------------------------------------- 1 | import type { AbstractConstructor, Constructor } from '@wener/utils'; 2 | 3 | export function getObjectName(Type: Constructor | AbstractConstructor) { 4 | return Type.name.replace(/Object$/, ''); 5 | } 6 | 7 | export function getInputName(Type: Constructor | AbstractConstructor) { 8 | return Type.name.replace(/Input$/, ''); 9 | } 10 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/type-graphql/getTypeCache.ts: -------------------------------------------------------------------------------- 1 | import { getGlobalStates } from '@wener/utils'; 2 | 3 | export function getTypeCache() { 4 | return getGlobalStates('TypeGraphQLTypeCache', () => new Map()); 5 | } 6 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/type-graphql/mixins/const.ts: -------------------------------------------------------------------------------- 1 | export const EmptyArray = []; 2 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/type-graphql/resolveGraphQLJSON.ts: -------------------------------------------------------------------------------- 1 | import { get } from '@wener/utils'; 2 | import type { JSONArgs } from './JSONArgs'; 3 | 4 | export function resolveGraphQLJSON(a: any, args: JSONArgs) { 5 | let o = a; 6 | if (args.path) { 7 | o = get(o, args.path); 8 | } 9 | if (args.default !== undefined) { 10 | o = o ?? args.default; 11 | } 12 | return o; 13 | } 14 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/type-graphql/resolver/HasTagsResolver.ts: -------------------------------------------------------------------------------- 1 | import { Arg, FieldResolver, Resolver, Root } from 'type-graphql'; 2 | import { HasTagsNode } from '../interface'; 3 | 4 | @Resolver(() => HasTagsNode) 5 | export class HasTagsResolver { 6 | @FieldResolver(() => Boolean) 7 | hasTag(@Root() root: HasTagsNode, @Arg('tag') tag: string) { 8 | return Boolean(root.tags?.includes(tag)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/type-graphql/resolver/index.ts: -------------------------------------------------------------------------------- 1 | export { HasTagsResolver } from './HasTagsResolver'; 2 | export { HasMetadataResolver } from './HasMetadataResolver'; 3 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/type-graphql/resource/OnConflictInput.ts: -------------------------------------------------------------------------------- 1 | import { Field, InputType } from 'type-graphql'; 2 | 3 | @InputType() 4 | export class OnConflictInput { 5 | @Field(() => [String], { nullable: true }) 6 | fields?: string[]; 7 | 8 | @Field(() => String, { nullable: true }) 9 | action?: string; 10 | 11 | @Field(() => [String], { nullable: true }) 12 | merge?: string[]; 13 | 14 | @Field(() => [String], { nullable: true }) 15 | exclude?: string[]; 16 | } 17 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/type-graphql/resource/index.ts: -------------------------------------------------------------------------------- 1 | export { OnConflictInput } from './OnConflictInput'; 2 | export { ListQueryInput } from './ListQueryInput'; 3 | export { createListPayload } from './createListPayload'; 4 | export { ResField } from './ResField'; 5 | export { withBaseQuery } from './withBaseQuery'; 6 | export * from './createBaseEntityResolver'; 7 | export * from './factory'; 8 | export * from './args'; 9 | export * from './types'; 10 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/type-graphql/types.ts: -------------------------------------------------------------------------------- 1 | export type EntityClass = Function & { 2 | prototype: T; 3 | }; 4 | 5 | export type ObjectClass = Function & { 6 | prototype: T; 7 | }; 8 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/types.ts: -------------------------------------------------------------------------------- 1 | export type AbstractConstructor = abstract new (...args: any[]) => T; 2 | export type Constructor = new (...args: any[]) => T; 3 | export type Optional = Omit & Partial>; 4 | -------------------------------------------------------------------------------- /packages/wener-nestjs/src/yoga/index.ts: -------------------------------------------------------------------------------- 1 | export type {}; 2 | -------------------------------------------------------------------------------- /packages/wener-reaction/rollup.bundle.mjs: -------------------------------------------------------------------------------- 1 | import { createBundle } from '@wener/wode/rollup.mjs'; 2 | 3 | export default createBundle() 4 | -------------------------------------------------------------------------------- /packages/wener-reaction/rollup.dev.mjs: -------------------------------------------------------------------------------- 1 | import { dev } from '@wener/wode/rollup.mjs'; 2 | 3 | export default dev 4 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/components/ClientOnly.tsx: -------------------------------------------------------------------------------- 1 | import type { FC } from 'react'; 2 | import { renderAlternative, type AlternativeRendererProps } from '../render/renderAlternative'; 3 | 4 | export const ClientOnly: FC = (props) => { 5 | return renderAlternative(typeof window !== 'undefined', props); 6 | }; 7 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/components/DevOnly.tsx: -------------------------------------------------------------------------------- 1 | import type { FC } from 'react'; 2 | import { renderAlternative, type AlternativeRendererProps } from '../render/renderAlternative'; 3 | 4 | export const DevOnly: FC = (props) => { 5 | const dev = process.env.NODE_ENV === 'development'; 6 | return renderAlternative(dev, props); 7 | }; 8 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/components/MountedOnly.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import type { FC } from 'react'; 4 | import { useMounted } from '../hooks/useMounted'; 5 | import { renderAlternative, type AlternativeRendererProps } from '../render/renderAlternative'; 6 | 7 | /** 8 | * Only render when mounted or client side 9 | */ 10 | export const MountedOnly: FC = (props) => { 11 | const mounted = useMounted(); 12 | return renderAlternative(mounted, props); 13 | }; 14 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/components/ProdOnly.tsx: -------------------------------------------------------------------------------- 1 | import type { FC } from 'react'; 2 | import { renderAlternative, type AlternativeRendererProps } from '../render/renderAlternative'; 3 | 4 | export const ProdOnly: FC = (props) => { 5 | const dev = process.env.NODE_ENV === 'production'; 6 | return renderAlternative(dev, props); 7 | }; 8 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/components/ServerOnly.tsx: -------------------------------------------------------------------------------- 1 | 'use server'; 2 | 3 | import type { FC } from 'react'; 4 | import { renderAlternative, type AlternativeRendererProps } from '../render/renderAlternative'; 5 | 6 | export const ServerOnly: FC = (props) => { 7 | let isServer = typeof window === 'undefined'; 8 | return renderAlternative(isServer, props); 9 | }; 10 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/hooks/useConstant.ts: -------------------------------------------------------------------------------- 1 | import { useRef } from 'react'; 2 | 3 | /** 4 | * create only once 5 | * 6 | * @see https://reactjs.org/docs/hooks-faq.html#how-to-create-expensive-objects-lazily 7 | * @see https://github.com/Andarist/use-constant/blob/master/src/index.ts 8 | */ 9 | export function useConstant(fn: () => T): T { 10 | const ref = useRef<{ v: T }>(); 11 | 12 | if (!ref.current) { 13 | ref.current = { v: fn() }; 14 | } 15 | 16 | return ref.current.v; 17 | } 18 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/hooks/useDeepCompareHooks.ts: -------------------------------------------------------------------------------- 1 | import { deepEqual } from '@wener/utils'; 2 | import { createDeepCompareHooks } from '../utils/createDeepCompareHooks'; 3 | 4 | const { useDeepCompareMemoize, useDeepCompareCallback, useDeepCompareEffect, useDeepCompareMemo } = 5 | createDeepCompareHooks(deepEqual); 6 | 7 | export { useDeepCompareMemoize, useDeepCompareCallback, useDeepCompareEffect, useDeepCompareMemo }; 8 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/hooks/useDeepEqual.tsx: -------------------------------------------------------------------------------- 1 | import { useRef } from 'react'; 2 | import { deepEqual } from '@wener/utils'; 3 | 4 | export function useDeepEqual(selector: (state: S) => U): (state: S) => U { 5 | // https://github.com/pmndrs/zustand/blob/main/src/react/shallow.ts 6 | const prev = useRef(); 7 | return (state) => { 8 | const next = selector(state); 9 | return deepEqual(prev.current, next) ? (prev.current as U) : (prev.current = next); 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/hooks/useEffectOnce.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, type EffectCallback } from 'react'; 2 | 3 | /** 4 | * useEffectOnce only run effect one 5 | * @param effect 6 | */ 7 | export function useEffectOnce(effect: EffectCallback) { 8 | useEffect(effect, []); 9 | } 10 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/hooks/useForceRender.ts: -------------------------------------------------------------------------------- 1 | import { useReducer } from 'react'; 2 | 3 | /** 4 | * useForceRender return a forceRender function to fore rerender current component 5 | */ 6 | export function useForceRender() { 7 | const [, forceRender] = useReducer((s: number) => s + 1, 0); 8 | return forceRender; 9 | } 10 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/hooks/useIsoMorphicEffect.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useLayoutEffect } from 'react'; 2 | 3 | export const useIsoMorphicEffect = typeof document === 'undefined' ? useEffect : useLayoutEffect; 4 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/hooks/useLatestValue.ts: -------------------------------------------------------------------------------- 1 | import { useRef } from 'react'; 2 | import { useIsoMorphicEffect } from './useIsoMorphicEffect'; 3 | 4 | export function useLatestValue(value: T) { 5 | const cache = useRef(value); 6 | 7 | useIsoMorphicEffect(() => { 8 | cache.current = value; 9 | }, [value]); 10 | 11 | return cache; 12 | } 13 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/hooks/useMounted.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | /** 4 | * 配合 nextjs 可以实现只有客户端才渲染的组件 5 | * @see https://github.com/zeit/next.js/blob/canary/examples/progressive-render/pages/index.js 6 | */ 7 | export function useMounted() { 8 | const [mounted, setMounted] = useState(false); 9 | useEffect(() => setMounted(true), []); 10 | return mounted; 11 | } 12 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/hooks/usePrevious.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react'; 2 | 3 | /** 4 | * usePrevious will return previous value without state change 5 | */ 6 | export function usePrevious(value: T) { 7 | const ref = useRef(); 8 | useEffect(() => { 9 | ref.current = value; 10 | }, [value]); 11 | return ref.current; 12 | } 13 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/hooks/useRenderCount.ts: -------------------------------------------------------------------------------- 1 | import { useRef } from 'react'; 2 | 3 | /** 4 | * useRenderCount return a count of render times 5 | */ 6 | export function useRenderCount() { 7 | const ref = useRef(0); 8 | return ++ref.current; 9 | } 10 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/next/index.ts: -------------------------------------------------------------------------------- 1 | export { NextNavLink } from './NextNavLink'; 2 | export type * from './types'; 3 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/next/types.ts: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react'; 2 | 3 | export interface NextPageProps

, S = Record> { 4 | params: P; 5 | searchParams: S; 6 | } 7 | 8 | export interface NextLayoutProps

> { 9 | params: P; 10 | children?: ReactNode; 11 | } 12 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/render/FlexRenderer.tsx: -------------------------------------------------------------------------------- 1 | import { flexRender, type FlexRenderable } from './flexRender'; 2 | 3 | export type FlexRendererProps

= P & { 4 | render?: FlexRenderable

; 5 | children?: FlexRenderable

; 6 | }; 7 | 8 | export function FlexRenderer

({ children, render = children, ...props }: FlexRendererProps

) { 9 | return flexRender(render, props as any); 10 | } 11 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/render/renderAlternative.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react'; 2 | 3 | export interface AlternativeRendererProps { 4 | children?: ReactNode; 5 | render?: () => ReactNode; 6 | fallback?: ReactNode; 7 | } 8 | 9 | export function renderAlternative(alt: boolean, { children, fallback, render }: AlternativeRendererProps) { 10 | return alt ? (render ? render() : children) : fallback; 11 | } 12 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/store/index.ts: -------------------------------------------------------------------------------- 1 | export { getNetworkStatus, useNetworkStatus } from './NetworkStatus'; 2 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/typing.ts: -------------------------------------------------------------------------------- 1 | export type Equivalence = (a: A, b: B) => boolean; 2 | 3 | export type Selector = (a: T) => V; 4 | export type UseSelector = (selector: Selector, eq?: Equivalence) => V; 5 | 6 | export type Optional = Omit & Partial; 7 | export type PartialRequired = Partial> & Required>; 8 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/universal.ts: -------------------------------------------------------------------------------- 1 | export { flexRender, type FlexRenderable } from './render/flexRender'; 2 | export { renderAlternative, type AlternativeRendererProps } from './render/renderAlternative'; 3 | export { isReactComponent } from './render/isReactComponent'; 4 | export { mergeRefs } from './utils/mergeRefs'; 5 | export { mergeProps } from './utils/mergeProps'; 6 | export { DevOnly } from './components/DevOnly'; 7 | export { ProdOnly } from './components/ProdOnly'; 8 | -------------------------------------------------------------------------------- /packages/wener-reaction/src/valtio/index.ts: -------------------------------------------------------------------------------- 1 | export { proxyWithCompare } from './proxyWithCompare'; 2 | export { proxyWith } from './proxyWith'; 3 | -------------------------------------------------------------------------------- /packages/wener-reaction/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": ["src/index.ts"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/wener-reaction/types.d.ts: -------------------------------------------------------------------------------- 1 | declare var __DEV__: boolean; 2 | 3 | interface ImportMetaEnv extends Readonly> { 4 | readonly MODE: string; 5 | readonly BASE_URL: string; 6 | readonly DEV: boolean; 7 | readonly PROD: boolean; 8 | readonly SSR: boolean; 9 | } 10 | 11 | interface ImportMeta { 12 | readonly env: ImportMetaEnv; 13 | } 14 | 15 | namespace NodeJS { 16 | interface ProcessEnv { 17 | readonly NODE_ENV: 'development' | 'production' | 'test'; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/wener-utils/.prettierignore: -------------------------------------------------------------------------------- 1 | data.json 2 | -------------------------------------------------------------------------------- /packages/wener-utils/rollup.bundle.mjs: -------------------------------------------------------------------------------- 1 | import { prod } from '@wener/wode/rollup.mjs'; 2 | 3 | export default { 4 | input: prod.input, 5 | output: prod.output, 6 | plugins: prod.plugins, 7 | external: prod.external, 8 | }; 9 | -------------------------------------------------------------------------------- /packages/wener-utils/rollup.dev.mjs: -------------------------------------------------------------------------------- 1 | import { dev } from '@wener/wode/rollup.mjs'; 2 | 3 | export default { 4 | input: dev.input, 5 | output: dev.output, 6 | plugins: dev.plugins, 7 | external: dev.external, 8 | }; 9 | -------------------------------------------------------------------------------- /packages/wener-utils/src/arrays/arrayFromAsync.ts: -------------------------------------------------------------------------------- 1 | export async function arrayFromAsync(asyncIterable: AsyncIterable): Promise { 2 | const array = []; 3 | for await (const i of asyncIterable) array.push(i); 4 | return array; 5 | } 6 | -------------------------------------------------------------------------------- /packages/wener-utils/src/asyncs/AsyncInterval.ts: -------------------------------------------------------------------------------- 1 | export type AsyncIntervalIdentifier = any; 2 | 3 | export function setAsyncInterval(cb: () => void, interval: number, initial = interval): AsyncIntervalIdentifier { 4 | let id: any; 5 | const handler = async () => { 6 | await cb(); 7 | id = setTimeout(handler, interval); 8 | }; 9 | id = setTimeout(handler, initial); 10 | return () => id; 11 | } 12 | 13 | export function clearAsyncInterval(v: AsyncIntervalIdentifier) { 14 | clearTimeout(v?.()); 15 | } 16 | -------------------------------------------------------------------------------- /packages/wener-utils/src/asyncs/MaybePromise.ts: -------------------------------------------------------------------------------- 1 | export type MaybePromise = Promise | T; 2 | -------------------------------------------------------------------------------- /packages/wener-utils/src/asyncs/firstOfAsyncIterator.ts: -------------------------------------------------------------------------------- 1 | import { isPromise } from './isPromise'; 2 | import type { MaybePromise } from './MaybePromise'; 3 | import { nextOfAsyncIterator } from './nextOfAsyncIterator'; 4 | 5 | export function firstOfAsyncIterator(it: MaybePromise | Iterator | T>): MaybePromise { 6 | const next = nextOfAsyncIterator(it); 7 | if (isPromise(next)) { 8 | return next.then((v) => v[0]); 9 | } 10 | return next[0]; 11 | } 12 | -------------------------------------------------------------------------------- /packages/wener-utils/src/asyncs/generatorOfStream.ts: -------------------------------------------------------------------------------- 1 | export function* generatorOfStream(stream: any): IterableIterator> { 2 | let done = false; 3 | stream.on('end', () => { 4 | done = true; 5 | }); 6 | // eslint-disable-next-line no-unmodified-loop-condition 7 | while (!done) { 8 | yield new Promise((resolve, reject) => { 9 | stream.once('data', resolve); 10 | stream.once('end', resolve); 11 | stream.once('error', reject); 12 | }); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/wener-utils/src/asyncs/isIterator.ts: -------------------------------------------------------------------------------- 1 | export function isIterator(it: any): it is Iterator | AsyncIterator { 2 | return typeof it?.next === 'function'; 3 | } 4 | -------------------------------------------------------------------------------- /packages/wener-utils/src/asyncs/isPromise.ts: -------------------------------------------------------------------------------- 1 | import { Promises } from './Promises'; 2 | 3 | export const isPromise = Promises.isPromise; 4 | -------------------------------------------------------------------------------- /packages/wener-utils/src/asyncs/isThenable.ts: -------------------------------------------------------------------------------- 1 | export function isThenable(v: any): v is PromiseLike { 2 | // we are at Promise era now, so we can use Promise instead of PromiseLike 3 | return v && typeof v.then === 'function'; 4 | } 5 | -------------------------------------------------------------------------------- /packages/wener-utils/src/asyncs/promiseOfCallback.ts: -------------------------------------------------------------------------------- 1 | export function promiseOfCallback(fun: (cb: (err: any, val?: T) => void) => void) { 2 | return new Promise((resolve, reject) => { 3 | try { 4 | fun((e: any, v: any) => { 5 | if (e) { 6 | reject(e); 7 | } else { 8 | resolve(v); 9 | } 10 | }); 11 | } catch (e) { 12 | reject(e); 13 | } 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /packages/wener-utils/src/cn/README.md: -------------------------------------------------------------------------------- 1 | - id 2 | - https://zh.wikipedia.org/wiki/中华人民共和国外国人永久居留身份证 3 | - https://learn.microsoft.com/en-us/purview/sit-defn-china-resident-identity-card-number 4 | -------------------------------------------------------------------------------- /packages/wener-utils/src/cn/pinyin/loader.ts: -------------------------------------------------------------------------------- 1 | import { setCharToPinyinTable } from './toPinyinPure'; 2 | import { transformData } from './transform'; 3 | 4 | export function loadCharToPinyinTable(): Promise> { 5 | return import('./data.json' as unknown as string, { with: { type: 'json' } }) 6 | .then((v) => v.default as Record) 7 | .then((data) => { 8 | let out = transformData(data); 9 | setCharToPinyinTable(out); 10 | return out; 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /packages/wener-utils/src/cn/pinyin/preload.ts: -------------------------------------------------------------------------------- 1 | import { loadCharToPinyinTable } from './loader'; 2 | 3 | await loadCharToPinyinTable(); 4 | -------------------------------------------------------------------------------- /packages/wener-utils/src/cn/pinyin/toPinyin.test.ts: -------------------------------------------------------------------------------- 1 | import { assert, test } from 'vitest'; 2 | import { loadCharToPinyinTable } from './loader'; 3 | import { toPinyinPure } from './toPinyinPure'; 4 | 5 | test('toPinyin', async () => { 6 | await loadCharToPinyinTable(); 7 | assert.deepEqual(toPinyinPure('真思'), ['zhen,sai', 'zhen,si']); 8 | 9 | // char to py -> 350k 10 | // py to char -> 145k 11 | // csv -> 96k 12 | }); 13 | -------------------------------------------------------------------------------- /packages/wener-utils/src/cn/pinyin/transform.ts: -------------------------------------------------------------------------------- 1 | export function transformData(input: Record) { 2 | let out = {} as Record; 3 | for (let [py, chars] of Object.entries(input)) { 4 | for (let c of chars) { 5 | if (!out[c]) { 6 | out[c] = []; 7 | } 8 | out[c].push(py); 9 | } 10 | } 11 | return out; 12 | } 13 | -------------------------------------------------------------------------------- /packages/wener-utils/src/cn/types.ts: -------------------------------------------------------------------------------- 1 | export interface StringFormat { 2 | regex?: RegExp; 3 | validate: (s: string) => boolean; 4 | generate: (opts?: GenerateOptions) => ParsedObject; 5 | parse: (s: string) => ParsedObject | undefined; 6 | } 7 | 8 | export interface StringChecksum { 9 | validate: (s: string) => boolean; 10 | generate: (s: string) => string; 11 | } 12 | -------------------------------------------------------------------------------- /packages/wener-utils/src/cn/uscc/isUSCC.ts: -------------------------------------------------------------------------------- 1 | import { USCC } from './USCC'; 2 | 3 | /** 4 | * USCC - 统一社会信用代码 5 | */ 6 | export function isUSCC(s: string) { 7 | return USCC.validate(s); 8 | } 9 | -------------------------------------------------------------------------------- /packages/wener-utils/src/cn/uscc/uscc.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from 'vitest'; 2 | import { isUSCC } from './isUSCC'; 3 | import { Mod31 } from './Mod31'; 4 | import { USCC } from './USCC'; 5 | 6 | test('uscc', () => { 7 | let cs = Mod31; 8 | 9 | // 阿里云计算 10 | expect(cs.validate('91330106673959654P')).toBeTruthy(); 11 | expect(cs.compute('91330106673959654')).toBe('P'); 12 | 13 | expect(isUSCC('91330106673959654P')).toBeTruthy(); 14 | 15 | console.log(USCC.parse('91330106673959654P')); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/wener-utils/src/crypto/base.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * hex string 3 | */ 4 | export function hex(s: Uint8Array | ArrayBuffer) { 5 | return Array.from(new Uint8Array(s)) 6 | .map((v) => v.toString(16).padStart(2, '0')) 7 | .join(''); 8 | } 9 | -------------------------------------------------------------------------------- /packages/wener-utils/src/crypto/md5.d.ts: -------------------------------------------------------------------------------- 1 | export function md5(s: string): string; 2 | -------------------------------------------------------------------------------- /packages/wener-utils/src/crypto/md5.test.ts: -------------------------------------------------------------------------------- 1 | import { assert, describe, test } from 'vitest'; 2 | import { md5 } from './md5'; 3 | 4 | describe('md5', () => { 5 | test('js', () => { 6 | assert.equal(md5(''), 'd41d8cd98f00b204e9800998ecf8427e'); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/wener-utils/src/crypto/pem/__snapshots__/pem.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`cases 1`] = ` 4 | "-----BEGIN RSA PRIVATE KEY----- 5 | SGVsbG8= 6 | -----END RSA PRIVATE KEY----- 7 | " 8 | `; 9 | 10 | exports[`cases 2`] = ` 11 | "-----BEGIN RSA PRIVATE KEY----- 12 | Name: N-:1/= 13 | Age: 1234 14 | 15 | TmljZQ== 16 | -----END RSA PRIVATE KEY----- 17 | " 18 | `; 19 | -------------------------------------------------------------------------------- /packages/wener-utils/src/fetch/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './types'; 2 | export { createFetchWith } from './createFetchWith'; 3 | export { createFetchWithLogging } from './createFetchWithLogging'; 4 | export { dumpRequest } from './dumpRequest'; 5 | export { dumpResponse } from './dumpResponse'; 6 | export { createFetchWithRetry, type FetchWithRetryOptions } from './createFetchWithRetry'; 7 | -------------------------------------------------------------------------------- /packages/wener-utils/src/fetch/types.ts: -------------------------------------------------------------------------------- 1 | export type FetchLike = ( 2 | url: string | URL | Request, 3 | init?: R, 4 | ) => Promise; 5 | -------------------------------------------------------------------------------- /packages/wener-utils/src/io/ArrayBuffer.test-d.ts: -------------------------------------------------------------------------------- 1 | import { expectTypeOf, test } from 'vitest'; 2 | import { ArrayBuffers } from './ArrayBuffers'; 3 | 4 | test('my types work properly', () => { 5 | expectTypeOf(ArrayBuffers.asView(Buffer, new Uint8Array())).toMatchTypeOf(); 6 | }); 7 | -------------------------------------------------------------------------------- /packages/wener-utils/src/io/isBuffer.test.ts: -------------------------------------------------------------------------------- 1 | import { Buffer } from 'node:buffer'; 2 | import { expect, test } from 'vitest'; 3 | import { classOf } from '../langs/classOf'; 4 | import { isBuffer } from './isBuffer'; 5 | 6 | test('isBuffer', () => { 7 | expect(isBuffer(Buffer.from(''))).toBeTruthy(); 8 | expect(classOf(Buffer)).toBe('Function'); 9 | }); 10 | -------------------------------------------------------------------------------- /packages/wener-utils/src/io/isBuffer.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * check {@link obj} is Buffer 3 | * 4 | * @see {@link https://github.com/feross/is-buffer feross/is-buffer} 5 | */ 6 | export function isBuffer(obj: any): obj is Buffer { 7 | return obj?.constructor?.isBuffer?.(obj); 8 | } 9 | -------------------------------------------------------------------------------- /packages/wener-utils/src/io/isTransferable.test.ts: -------------------------------------------------------------------------------- 1 | import { Buffer } from 'node:buffer'; 2 | import { expect, test } from 'vitest'; 3 | import { isTransferable } from './isTransferable'; 4 | 5 | test('isTransferable', () => { 6 | expect(isTransferable(0)).toBeFalsy(); 7 | expect(isTransferable(Buffer.from(''))).toBeFalsy(); 8 | 9 | expect(new ArrayBuffer(0) instanceof ArrayBuffer).toBeTruthy(); 10 | expect(isTransferable(new ArrayBuffer(0))).toBeTruthy(); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/wener-utils/src/langs/MaybeFunction.ts: -------------------------------------------------------------------------------- 1 | export type MaybeFunction = T | ((...args: P) => T); 2 | 3 | export function maybeFunction(v: MaybeFunction, ...args: P): T { 4 | // https://github.com/microsoft/TypeScript/issues/37663#issuecomment-759728342 5 | if (v instanceof Function) { 6 | return v(...args); 7 | } 8 | return v; 9 | } 10 | -------------------------------------------------------------------------------- /packages/wener-utils/src/langs/README.md: -------------------------------------------------------------------------------- 1 | # Core 2 | 3 | - https://github.com/angus-c/just 4 | - lodash 5 | - mixin https://github.com/1nVitr0/lib-ts-mixin-extended 6 | - https://developer.mozilla.org/docs/Web/JavaScript/Reference/Classes#Mix-ins 7 | - http://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/ 8 | - https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html 9 | -------------------------------------------------------------------------------- /packages/wener-utils/src/langs/classOf.ts: -------------------------------------------------------------------------------- 1 | export function classOf(o: any) { 2 | return Object.prototype.toString.call(o).slice(8, -1); 3 | } 4 | -------------------------------------------------------------------------------- /packages/wener-utils/src/langs/deepEqual.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from 'vitest'; 2 | import { deepEqual } from './deepEqual'; 3 | 4 | test('deep equal', () => { 5 | expect( 6 | deepEqual( 7 | { 8 | a: null, 9 | b: Infinity, 10 | }, 11 | { 12 | a: null, 13 | b: Infinity, 14 | }, 15 | ), 16 | ).toBeTruthy(); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/wener-utils/src/langs/getObjectId.ts: -------------------------------------------------------------------------------- 1 | import { getGlobalStates } from './getGlobalStates'; 2 | 3 | export function getObjectId(k: any): number { 4 | const state = getGlobalStates('ObjectId', () => { 5 | return { 6 | id: 1, 7 | map: new WeakMap(), 8 | }; 9 | }); 10 | 11 | const { map } = state; 12 | 13 | if (map.has(k)) { 14 | return map.get(k); 15 | } 16 | 17 | const id = state.id++; 18 | map.set(k, id); 19 | return id; 20 | } 21 | -------------------------------------------------------------------------------- /packages/wener-utils/src/langs/ifPresent.ts: -------------------------------------------------------------------------------- 1 | export function ifPresent(value: T, fn: (v: NonNullable) => R): R | undefined { 2 | return value ? fn(value) : undefined; 3 | } 4 | -------------------------------------------------------------------------------- /packages/wener-utils/src/langs/isClass.ts: -------------------------------------------------------------------------------- 1 | export function isClass(func: any) { 2 | return typeof func === 'function' && /^class\s/.test(Function.prototype.toString.call(func)); 3 | } 4 | -------------------------------------------------------------------------------- /packages/wener-utils/src/langs/isDefined.ts: -------------------------------------------------------------------------------- 1 | export function isDefined(v: T): v is NonNullable { 2 | return v !== null && v !== undefined; 3 | } 4 | -------------------------------------------------------------------------------- /packages/wener-utils/src/langs/isEmptyObject.ts: -------------------------------------------------------------------------------- 1 | import { isPlainObject } from './isPlainObject'; 2 | 3 | export function isEmptyObject(o: any) { 4 | return isPlainObject(o) && Object.keys(o).length === 0; 5 | } 6 | -------------------------------------------------------------------------------- /packages/wener-utils/src/langs/isFunction.ts: -------------------------------------------------------------------------------- 1 | export function isFunction(value: any): value is Function { 2 | return typeof value === 'function'; 3 | } 4 | -------------------------------------------------------------------------------- /packages/wener-utils/src/langs/isNullish.ts: -------------------------------------------------------------------------------- 1 | export function isNullish(value: any): value is null | undefined { 2 | return value === null || value === undefined; 3 | } 4 | -------------------------------------------------------------------------------- /packages/wener-utils/src/langs/isPlainObject.ts: -------------------------------------------------------------------------------- 1 | import { classOf } from './classOf'; 2 | 3 | // see: https://github.com/mesqueeb/is-what/blob/88d6e4ca92fb2baab6003c54e02eedf4e729e5ab/src/index.ts 4 | 5 | export function isPlainObject(value: any): value is Record { 6 | if (classOf(value) !== 'Object') { 7 | return false; 8 | } 9 | return value.constructor === Object && Object.getPrototypeOf(value) === Object.prototype; 10 | } 11 | -------------------------------------------------------------------------------- /packages/wener-utils/src/langs/shallowClone.ts: -------------------------------------------------------------------------------- 1 | export function shallowClone(obj: T): T { 2 | if (!obj) { 3 | return obj; 4 | } 5 | if (Array.isArray(obj)) { 6 | return obj.slice() as T; 7 | } 8 | if (typeof obj === 'object') { 9 | return Object.assign({}, obj); 10 | } 11 | // skip Map, Set, WeakMap, WeakSet, Date, RegExp, etc. 12 | return obj; 13 | } 14 | -------------------------------------------------------------------------------- /packages/wener-utils/src/libs/README.md: -------------------------------------------------------------------------------- 1 | - https://github.com/vercel/ms/blob/master/src/index.ts 2 | - Apr 22, 2022 3 | - dfd18036f359a3b80bf38d3d8c0bb850c0dc9b66 4 | -------------------------------------------------------------------------------- /packages/wener-utils/src/logging/createNoopLogger.ts: -------------------------------------------------------------------------------- 1 | import type { LoggerWithChild } from './Logger'; 2 | 3 | export function createNoopLogger(): LoggerWithChild { 4 | const noop = (..._: any[]) => undefined; 5 | return { 6 | trace: noop, 7 | debug: noop, 8 | info: noop, 9 | warn: noop, 10 | error: noop, 11 | child: () => createNoopLogger(), 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /packages/wener-utils/src/logging/slog.test.ts: -------------------------------------------------------------------------------- 1 | import { test } from 'vitest'; 2 | import { createLogger } from './slog'; 3 | 4 | test('slog', () => { 5 | const log = createLogger(); 6 | log.info('hello'); 7 | log.debug('hello', { name: 'wener', age: 18 }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/wener-utils/src/maths/createRandom.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from 'vitest'; 2 | import { createRandom } from './random'; 3 | 4 | test('createRandom', () => { 5 | let random = createRandom(0); 6 | expect(random.random(100)).toBe(47); 7 | for (const a of random) { 8 | expect(a).toBe(0.557133817113936); 9 | break; 10 | } 11 | expect(random.randomBytes(4)).toEqual(Uint8Array.from([163, 85, 196, 62])); 12 | }); 13 | -------------------------------------------------------------------------------- /packages/wener-utils/src/mitt/README.md: -------------------------------------------------------------------------------- 1 | - https://github.com/developit/mitt/blob/main/src/index.ts 2 | -------------------------------------------------------------------------------- /packages/wener-utils/src/modules/isModule.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Check is ESM Module 3 | */ 4 | export function isModule(o: any): o is Module { 5 | return o && o[Symbol.toStringTag] === 'Module'; 6 | } 7 | 8 | export interface Module { 9 | [Symbol.toStringTag]: 'Module'; 10 | default?: any; 11 | 12 | [k: string | symbol]: any; 13 | } 14 | -------------------------------------------------------------------------------- /packages/wener-utils/src/objects/merge/index.ts: -------------------------------------------------------------------------------- 1 | export { merge, type MergeOptions } from './merge'; 2 | -------------------------------------------------------------------------------- /packages/wener-utils/src/schema/typebox/index.ts: -------------------------------------------------------------------------------- 1 | export * as TypeBox from './typebox'; 2 | -------------------------------------------------------------------------------- /packages/wener-utils/src/server/crypto/md5.ts: -------------------------------------------------------------------------------- 1 | import { createHash } from 'node:crypto'; 2 | 3 | export function md5(input: Buffer | string) { 4 | return createHash('md5').update(input).digest('hex') as string; 5 | } 6 | -------------------------------------------------------------------------------- /packages/wener-utils/src/server/fetch/createFetchWithProxy.ts: -------------------------------------------------------------------------------- 1 | import { createFetchWithProxyByUndici } from './createFetchWithProxyByUndici'; 2 | 3 | export const createFetchWithProxy = createFetchWithProxyByUndici; 4 | -------------------------------------------------------------------------------- /packages/wener-utils/src/server/index.ts: -------------------------------------------------------------------------------- 1 | export { polyfillCrypto } from './polyfill/polyfillCrypto'; 2 | export { createFetchWithProxyByUndici } from './fetch/createFetchWithProxyByUndici'; 3 | export { createFetchWithProxy } from './fetch/createFetchWithProxy'; 4 | 5 | export { md5 } from './crypto/md5'; 6 | export { getPackageDir } from './getPackageDir'; 7 | -------------------------------------------------------------------------------- /packages/wener-utils/src/server/jsdom.ts: -------------------------------------------------------------------------------- 1 | export * from './polyfill/polyfillJsDom'; 2 | -------------------------------------------------------------------------------- /packages/wener-utils/src/server/node-fetch.ts: -------------------------------------------------------------------------------- 1 | export * from './polyfill/polyfillFetch'; 2 | export * from './fetch/createFetchWithProxyByNodeFetch'; 3 | -------------------------------------------------------------------------------- /packages/wener-utils/src/server/polyfill/polyfillCrypto.ts: -------------------------------------------------------------------------------- 1 | import { getGlobalThis } from '../../web/getGlobalThis'; 2 | 3 | export async function polyfillCrypto() { 4 | const globalThis = getGlobalThis(); 5 | if ('crypto' in globalThis) { 6 | return false; 7 | } 8 | (globalThis as any).crypto = (await import('node:crypto')).webcrypto as Crypto; 9 | return true; 10 | } 11 | -------------------------------------------------------------------------------- /packages/wener-utils/src/server/ws.ts: -------------------------------------------------------------------------------- 1 | export * from './polyfill/polyfillWebSocket'; 2 | -------------------------------------------------------------------------------- /packages/wener-utils/src/typedoc.ts: -------------------------------------------------------------------------------- 1 | export * from './index'; 2 | // fixme md5 conflict 3 | // export * from './server'; 4 | -------------------------------------------------------------------------------- /packages/wener-utils/src/validations/isUUID.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from 'vitest'; 2 | import { randomUUID } from '../web/randomUUID'; 3 | import { isUUID } from './isUUID'; 4 | 5 | test('isUUID', () => { 6 | for (const [a, b] of [ 7 | [undefined, false], 8 | [null, false], 9 | ['', false], 10 | [randomUUID(), true], 11 | ] as const) { 12 | expect(isUUID(a), `${a} -> ${b}`).toEqual(b); 13 | } 14 | }); 15 | -------------------------------------------------------------------------------- /packages/wener-utils/src/validations/isUUID.ts: -------------------------------------------------------------------------------- 1 | export function isUUID(str: string | undefined | null) { 2 | return Boolean(str) && /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(String(str)); 3 | } 4 | -------------------------------------------------------------------------------- /packages/wener-utils/src/validations/parseTimestamp.test.ts: -------------------------------------------------------------------------------- 1 | import { assert, test } from 'vitest'; 2 | import { parseTimestamp } from './parseTimestamp'; 3 | 4 | test('parseTimestamp', () => { 5 | assert.equal(parseTimestamp(''), undefined); 6 | assert.equal(parseTimestamp(), undefined); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/wener-utils/src/web/structuredClone.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from 'vitest'; 2 | import { classOf } from '../langs/classOf'; 3 | import { _clone } from './structuredClone'; 4 | 5 | test('structuredClone', () => { 6 | for (const [k, v] of [ 7 | ['', ''], 8 | [Number(1), 1], 9 | ]) { 10 | const c = _clone(k); 11 | expect(c).toEqual(v); 12 | expect(classOf(c)).toBe(classOf(v)); 13 | } 14 | }); 15 | -------------------------------------------------------------------------------- /packages/wener-utils/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": ["src/index.ts","src/server.ts"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/wener-utils/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config'; 2 | 3 | export default defineConfig({ 4 | test: { 5 | alias: { 6 | '@/': new URL('./src/', import.meta.url).pathname, 7 | }, 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'apps/*' 3 | - 'packages/*' 4 | - 'components/*' 5 | -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | 'tailwindcss/nesting': {}, 4 | tailwindcss: {}, 5 | autoprefixer: {}, 6 | ...(process.env.NODE_ENV === 'production' ? { cssnano: {} } : {}), 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /protos/bundles/google/protobuf/late_loaded_option.proto: -------------------------------------------------------------------------------- 1 | edition = "2023"; 2 | 3 | package protobuf_unittest; 4 | 5 | import "google/protobuf/descriptor.proto"; 6 | 7 | message LateLoadedOption { 8 | int32 value = 1; 9 | 10 | extend google.protobuf.MessageOptions { 11 | LateLoadedOption ext = 95126892; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /protos/bundles/google/protobuf/late_loaded_option_user.proto: -------------------------------------------------------------------------------- 1 | edition = "2023"; 2 | 3 | package protobuf_unittest; 4 | 5 | import "google/protobuf/late_loaded_option.proto"; 6 | 7 | message LateLoadedOptionUser { 8 | option (protobuf_unittest.LateLoadedOption.ext) = {value: 1}; 9 | } 10 | -------------------------------------------------------------------------------- /protos/bundles/google/type/README.md: -------------------------------------------------------------------------------- 1 | ## Google Common Types 2 | 3 | This package contains definitions of common types for Google APIs. 4 | All types defined in this package are suitable for different APIs to 5 | exchange data, and will never break binary compatibility. They should 6 | have design quality comparable to major programming languages like 7 | Java and C#. 8 | -------------------------------------------------------------------------------- /rollup.mjs: -------------------------------------------------------------------------------- 1 | export * from '@wener/wode/rollup.mjs'; 2 | --------------------------------------------------------------------------------