├── .devcontainer ├── Dockerfile └── devcontainer.json ├── .dockerignore ├── .eslintignore ├── .eslintrc.yml ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── boost-gitleaks.yml │ ├── boost-native.yml │ ├── boost-semgrep.yml │ ├── deploy-production.yml │ └── test-build-deploy.yml ├── .gitignore ├── .nvmrc ├── .prettierignore ├── .prettierrc.yaml ├── .snyk ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── terminals.json ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── SECURITY.md ├── backend ├── .bablerc ├── .gitignore ├── .prettierrc.yaml ├── .snyk ├── README.md ├── codegen-test.yml ├── codegen.yml ├── env-local.sh ├── env.sh ├── gulpfile.js ├── jest.config.js ├── meta │ ├── applicator │ ├── content │ ├── core │ ├── format │ ├── hyper-schema │ ├── hyper-schema-3 │ ├── meta-data │ ├── schema │ ├── schema-2 │ └── validation ├── ormconfig.js ├── package-lock.json ├── package.json ├── src │ ├── business │ │ └── CreateVersion.ts │ ├── context.ts │ ├── directive │ │ ├── ValidBase64ImageUploadDirective.ts │ │ ├── ValidCatalogSlugDirective.ts │ │ ├── ValidCollectionSlugDirective.ts │ │ ├── ValidEmailDirective.ts │ │ ├── ValidGroupSlugDirective.ts │ │ ├── ValidImageUploadDirective.ts │ │ ├── ValidMarkdownDirective.ts │ │ ├── ValidPackageSlugDirective.ts │ │ ├── ValidPasswordDirective.ts │ │ ├── ValidUsernameDirective.ts │ │ ├── ValidUsernameOrEmailAddressDirective.ts │ │ ├── ValidationConstraint.ts │ │ ├── ValidationType.ts │ │ ├── hasCatalogPermissionDirective.ts │ │ ├── hasCollectionPermissionDirective.ts │ │ ├── hasGroupPermissionDirective.ts.ts │ │ ├── hasPackagePermissionDirective.ts │ │ ├── isAuthenticatedDirective.ts │ │ ├── isSiteAdminDirective.ts │ │ └── isUserOrAdminDirective.ts │ ├── entity │ │ ├── APIKeyEntity.ts │ │ ├── ActivityLogEntity.ts │ │ ├── CatalogEntity.ts │ │ ├── CollectionEntity.ts │ │ ├── CollectionPackageEntity.ts │ │ ├── CredentialEntity.ts │ │ ├── DataBatchEntity.ts │ │ ├── EntityBaseModel.ts │ │ ├── FollowEntity.ts │ │ ├── GroupCatalogPermissionEntity.ts │ │ ├── GroupCollectionPermissionEntity.ts │ │ ├── GroupEntity.ts │ │ ├── GroupPackagePermissionEntity.ts │ │ ├── GroupUserEntity.ts │ │ ├── IssueCommentEntity.ts │ │ ├── PackageEntity.ts │ │ ├── PackageIssueEntity.ts │ │ ├── PackageIssueStatus.ts │ │ ├── Permissions.ts │ │ ├── PlatformSettingsEntity.ts │ │ ├── PlatformStateEntity.ts │ │ ├── RepositoryEntity.ts │ │ ├── UserCatalogPermissionEntity.ts │ │ ├── UserCollectionPermissionEntity.ts │ │ ├── UserEntity.ts │ │ ├── UserPackagePermissionEntity.ts │ │ ├── VersionComparisonEntity.ts │ │ ├── VersionDifferenceEntity.ts │ │ └── VersionEntity.ts │ ├── index.ts │ ├── job │ │ ├── BackendJobContextBase.ts │ │ ├── HeadlessJobContext.ts │ │ └── WebsocketJobContext.ts │ ├── migration │ │ ├── 1598392490897-initial.ts │ │ ├── 1598918058446-UserPassword.ts │ │ ├── 1599080105470-DontRequireNameOnSignUp.ts │ │ ├── 1599138803334-OptionalFields.ts │ │ ├── 1599181511316-APIKeyChanges.ts │ │ ├── 1599184202352-APIKeyChanges2.ts │ │ ├── 1599184609581-APIKeyChanges3.ts │ │ ├── 1599186350340-APIKeyChanges4.ts │ │ ├── 1599791266154-FullTextSearch-1.ts │ │ ├── 1599791878226-FullTextSearch-2.ts │ │ ├── 1599847062513-FullTextSearch-3.ts │ │ ├── 1599852332615-LowerCaseIndexes.ts │ │ ├── 1600130779808-FixTokensReference.ts │ │ ├── 1600181943280-CollectionsTableCreation.ts │ │ ├── 1600719428028-FixIndexUpdateScript.ts │ │ ├── 1600757487059-CollectionsSearchColumns.ts │ │ ├── 1600794387239-FixPackageUpdateTrigger.ts │ │ ├── 1600840245777-CreateCollectionAndPackageRelation.ts │ │ ├── 1601997753078-AddAuthorToVersions.ts │ │ ├── 1602010013926-CollectionCreator.ts │ │ ├── 1602027734941-PackageCreator.ts │ │ ├── 1602260763029-PackageVersionFKFix.ts │ │ ├── 1602690416153-ChangeDatesToTimestamptz.ts │ │ ├── 1602960936351-UserProperties.ts │ │ ├── 1603128229212-CreateImageTable.ts │ │ ├── 1603329332326-FixPackageSlugUniqueIndex.ts │ │ ├── 1603893535901-EmailVerification.ts │ │ ├── 1604719596366-AddVersionReadmeAndLicense.ts │ │ ├── 1604759899328-DropImageTable.ts │ │ ├── 1604787960095-DropFilesFromDatabase.ts │ │ ├── 1604879191849-DropIsActive.ts │ │ ├── 1605722637632-AddForgotPasswordToken.ts │ │ ├── 1605892679689-AddForgotPasswordTokenDate.ts │ │ ├── 1608649524913-ActivityLogTableCreation.ts │ │ ├── 1609167986147-ActivityLogUpdates.ts │ │ ├── 1609348606379-ActivityLogAddIndex.ts │ │ ├── 1609553026656-CatalogPackagePermissions.ts │ │ ├── 1609772972965-ActivityLogIncrementId.ts │ │ ├── 1609902949161-CatalogCreator.ts │ │ ├── 1610495666753-ActivityLogEventUpdates.ts │ │ ├── 1610566212911-DeleteAllPackages.ts │ │ ├── 1611026765149-InviteUser.ts │ │ ├── 1611269529488-UserStatus.ts │ │ ├── 1611872734083-AddCollectionViewedLogType.ts │ │ ├── 1612111338969-AddTargetUserColumnForActivityLogTable.ts │ │ ├── 1612112012161-AddUserStatusChangeActivityLogType.ts │ │ ├── 1614024797915-CreatePackageIssuesTables.ts │ │ ├── 1615996821186-AddUIDarkModeColumnToUserTable.ts │ │ ├── 1616091117502-CreatePackageVersionsDiffTables.ts │ │ ├── 1616546100576-CaseInsensitveValues.ts │ │ ├── 1617628711695-CreateFollowTable.ts │ │ ├── 1618415843311-AddVersionTrivialChangeType.ts │ │ ├── 1618418751085-AddTargetIssueIdColumnToActivityLogTable.ts │ │ ├── 1618864385071-CreatePlatformSettingsTable.ts │ │ ├── 1620666572765-AddUnclaimedCatalogColumn.ts │ │ ├── 1620769501264-MakeActivityLogTableChangeTypeColumnAVarChar.ts │ │ ├── 1622210412398-NotificationTimestamps.ts │ │ ├── 1624308986637-AddPackageIssueForeignKeyToLogsTable.ts │ │ ├── 1624567282854-PackageFollowCorrection.ts │ │ ├── 1624904654313-AddExtraNotificationFieldsToFollowEntity.ts │ │ ├── 1625845662069-AddUnclaimedLogTypesEnumToDbObject.ts │ │ ├── 1636656866265-CreateDataBatchTable.ts │ │ ├── 1643054963511-UpdateMethodToBatchTable.ts │ │ ├── 1643208391980-ActivityLogDataBatch.ts │ │ ├── 1647123024092-JobActivities.ts │ │ ├── 1648151610519-PackageLastUpdateJob.ts │ │ ├── 1649190799043-UpdateMethod.ts │ │ ├── 1657502298106-Credentials.ts │ │ ├── 1658499088645-Group.ts │ │ ├── 1660663641407-ActivityLogPermissions.ts │ │ ├── 1662041798173-PackagePermissions.ts │ │ ├── 1662572838241-GroupAdmin.ts │ │ ├── 1663619631799-CreatorIdFixes.ts │ │ └── 1668544666051-FetchJobActivities.ts │ ├── repository │ │ ├── APIKeyRepository.ts │ │ ├── ActivityLogRepository.ts │ │ ├── CatalogPermissionRepository.ts │ │ ├── CatalogRepository.ts │ │ ├── CollectionPackageRepository.ts │ │ ├── CollectionRepository.ts │ │ ├── CredentialRepository.ts │ │ ├── DataBatchRepository.ts │ │ ├── FollowRepository.ts │ │ ├── GroupCatalogPermissionRepository.ts │ │ ├── GroupCollectionPermissionRepository.ts │ │ ├── GroupPackagePermissionRepository.ts │ │ ├── GroupRepository.ts │ │ ├── GroupUserRepository.ts │ │ ├── OrderBy.ts │ │ ├── PackageIssueCommentRepository.ts │ │ ├── PackageIssueRepository.ts │ │ ├── PackagePermissionRepository.ts │ │ ├── PackageRepository.ts │ │ ├── PlatformSettingsRepository.ts │ │ ├── PlatformStateRepository.ts │ │ ├── RepositoryRepository.ts │ │ ├── UserCollectionPermissionRepository.ts │ │ ├── UserRepository.ts │ │ ├── VersionComparisonRepository.ts │ │ ├── VersionDifferenceRepository.ts │ │ └── VersionRepository.ts │ ├── resolvers.ts │ ├── resolvers │ │ ├── ActivityLogResolver.ts │ │ ├── ApiKeyResolver.ts │ │ ├── AuthResolver.ts │ │ ├── CatalogResolver.ts │ │ ├── CollectionResolver.ts │ │ ├── ConnectorsResolver.ts │ │ ├── CredentialResolver.ts │ │ ├── DateResolver.ts │ │ ├── FirstUserStatusHolder.ts │ │ ├── FollowResolver.ts │ │ ├── GroupCatalogPermissionResolver.ts │ │ ├── GroupCollectionPermissionResolver.ts │ │ ├── GroupPackagePermissionResolver.ts │ │ ├── GroupResolver.ts │ │ ├── JobResolver.ts │ │ ├── MeResolver.ts │ │ ├── PackageIssueCommentResolver.ts │ │ ├── PackageIssueResolver.ts │ │ ├── PackageResolver.ts │ │ ├── PlatformSettingsResolver.ts │ │ ├── RepositoryResolver.ts │ │ ├── UserCatalogPermissionResolver.ts │ │ ├── UserCollectionPermissionResolver.ts │ │ ├── UserPackagePermissionResolver.ts │ │ ├── UserResolver.ts │ │ ├── VersionComparisonResolver.ts │ │ └── VersionResolver.ts │ ├── schema.ts │ ├── service │ │ ├── distributed-locking-service.ts │ │ ├── leader-election-service.ts │ │ ├── notification-service.ts │ │ ├── package-update-service.ts │ │ └── reserved-keywords-service.ts │ ├── session-cache.ts │ ├── socket │ │ ├── DataFetchHandler.ts │ │ ├── DataUploadHandler.ts │ │ ├── FetchHandler.ts │ │ ├── PackageHandler.ts │ │ ├── PackageSinkStateHandler.ts │ │ ├── PackageStreamsHandler.ts │ │ ├── PackageUpdateHandler.ts │ │ ├── SetActiveBatchesHandler.ts │ │ └── SocketHandler.ts │ ├── storage │ │ ├── data │ │ │ └── data-storage.ts │ │ ├── dpm-storage-stream-holder.ts │ │ ├── dpm-storage.ts │ │ ├── file-storage.ts │ │ ├── files │ │ │ └── file-storage-service.ts │ │ ├── google-cloud-storage.ts │ │ ├── images │ │ │ ├── catalog-avatar-image-processor.ts │ │ │ ├── catalog-cover-image-processor.ts │ │ │ ├── collection-cover-image-processor.ts │ │ │ ├── image-processor.ts │ │ │ ├── image-storage-service.ts │ │ │ ├── package-cover-image-processor.ts │ │ │ ├── user-avatar-image-processor.ts │ │ │ └── user-cover-image-processor.ts │ │ ├── packages │ │ │ └── package-file-storage-service.ts │ │ └── storage-provider.ts │ ├── transforms │ │ └── BatchingTransform.ts │ ├── types │ │ ├── base62 │ │ │ └── index.d.ts │ │ ├── buffer-peek-stream │ │ │ └── index.d.ts │ │ └── minizlib │ │ │ └── index.d.ts │ └── util │ │ ├── AsyncUtils.ts │ │ ├── EncryptionUtil.spec.ts │ │ ├── EncryptionUtil.ts │ │ ├── GraphQLFieldsType.ts │ │ ├── IdentifierUtil.ts │ │ ├── PasswordUtil.spec.ts │ │ ├── PasswordUtil.ts │ │ ├── PermissionsUtil.ts │ │ ├── SiteMapUtil.ts │ │ ├── contextHelpers.ts │ │ ├── databaseCreation.ts │ │ ├── getEnvVariable.ts │ │ ├── jwt.ts │ │ ├── me.ts │ │ ├── notificationUtil.ts │ │ ├── prototypeExtensions.ts │ │ ├── relationNames.ts │ │ ├── secrets.ts │ │ └── smtpUtil.ts ├── startServer.sh ├── static │ ├── email-templates │ │ ├── api-key-created.html │ │ ├── api-key-created.txt │ │ ├── follow-notification.html │ │ ├── follow-notification.txt │ │ ├── forgot-password.html │ │ ├── forgot-password.txt │ │ ├── share-notification.html │ │ ├── share-notification.txt │ │ ├── user-invite.html │ │ ├── user-invite.txt │ │ ├── user-suspended.html │ │ ├── user-suspended.txt │ │ ├── validate-email-address.html │ │ └── validate-email-address.txt │ ├── index.html │ ├── robots-production.txt │ └── robots.txt ├── test │ ├── data-files │ │ ├── data.avro │ │ ├── postgres-test-data.sql │ │ ├── postgres-test-update.sql │ │ ├── simple │ │ │ ├── simple.LICENSE.md │ │ │ ├── simple.README.md │ │ │ ├── simple.csv │ │ │ └── simple.datapm.json │ │ └── start-small-donations.avro │ ├── data-server │ │ └── test-data-server.ts │ ├── integration │ │ ├── 0-test-user.ts │ │ ├── admin-holder.ts │ │ ├── constants.ts │ │ ├── setup.ts │ │ ├── test-activity-log.ts │ │ ├── test-admin-group.ts │ │ ├── test-admin-user.ts │ │ ├── test-apikey.ts │ │ ├── test-authentication.ts │ │ ├── test-autocomplete.ts │ │ ├── test-catalog-permission.ts │ │ ├── test-catalogs-slug-case.ts │ │ ├── test-catalogs.ts │ │ ├── test-collection-permission.ts │ │ ├── test-collection-search.ts │ │ ├── test-collection.ts │ │ ├── test-credentials.ts │ │ ├── test-email-verification.ts │ │ ├── test-follow.ts │ │ ├── test-followers.ts │ │ ├── test-following-catalog-activity-logs.ts │ │ ├── test-following-catalog-packages-notifications.ts │ │ ├── test-following-collection-activity-logs.ts │ │ ├── test-following-collection-packages-notifications.ts │ │ ├── test-following-notifications.ts │ │ ├── test-following-package-issue-activity-logs.ts │ │ ├── test-following-user-activity-logs.ts │ │ ├── test-forgot-password.ts │ │ ├── test-group-admin.ts │ │ ├── test-group-catalog.ts │ │ ├── test-group-collection.ts │ │ ├── test-group-package.ts │ │ ├── test-group.ts │ │ ├── test-image-uploads.ts │ │ ├── test-invite-user-package.ts │ │ ├── test-invite-user-sign-up.ts │ │ ├── test-move-package.ts │ │ ├── test-package-file-auto-upgrade.ts │ │ ├── test-package-issues.ts │ │ ├── test-package-publish-trivial-changes.ts │ │ ├── test-package-search.ts │ │ ├── test-package.ts │ │ ├── test-packages-recently-viewed.ts │ │ ├── test-page-content.ts │ │ ├── test-platform-settings.ts │ │ ├── test-registry-data.ts │ │ ├── test-registry-proxy.ts │ │ ├── test-user-case-sensitivity.ts │ │ ├── test-utils.ts │ │ ├── test-ws-update-no-auth.ts │ │ ├── test-ws-update-with-auth.ts │ │ └── test-ws-util.ts │ ├── other-files │ │ ├── ba.jpg │ │ └── ba.svg │ ├── packageFiles │ │ ├── congressional-legislators-updated.datapm.json │ │ ├── congressional-legislators-version-changed.datapm.json │ │ ├── congressional-legislators.LICENSE.md │ │ ├── congressional-legislators.README.md │ │ ├── congressional-legislators.datapm.json │ │ ├── test-update-package.LICENSE.md │ │ ├── test-update-package.README.md │ │ ├── test-update-package.datapm.json │ │ └── v0.1.0 │ │ │ ├── congressional-legislators-schema-v0.1.0.datapm.json │ │ │ ├── congressional-legislators.LICENSE.md │ │ │ └── congressional-legislators.README.md │ └── sources │ │ ├── state-codes.csv │ │ ├── update-test-changes.csv │ │ └── update-test-original.csv ├── tsconfig.json ├── tsconfig.module.json └── tslint.json ├── client-lib ├── .gitignore ├── CONNECTORS.md ├── PARSERS-SERIALIZERS.md ├── codegen.yml ├── gulpfile.js ├── package-lock.json ├── package.json ├── src │ ├── config │ │ └── Config.ts │ ├── connector │ │ ├── Connector.ts │ │ ├── ConnectorUtil.ts │ │ ├── Sink.ts │ │ ├── SinkUtil.ts │ │ ├── Source.ts │ │ ├── SourceUtil.ts │ │ ├── binance │ │ │ ├── BinanceConnector.ts │ │ │ ├── BinanceConnectorDescription.ts │ │ │ ├── BinanceSource.ts │ │ │ └── BinanceSourceDescription.ts │ │ ├── coinbase │ │ │ ├── CoinbaseConnector.ts │ │ │ ├── CoinbaseConnectorDescription.ts │ │ │ ├── CoinbaseSource.ts │ │ │ └── CoinbaseSourceDescription.ts │ │ ├── database │ │ │ ├── KnexSink.ts │ │ │ ├── big-query │ │ │ │ ├── BigQueryConnectorDescription.ts │ │ │ │ ├── BigQueryRepository.ts │ │ │ │ ├── BigQuerySink.ts │ │ │ │ ├── BigQuerySinkDescription.ts │ │ │ │ ├── BigQuerySource.ts │ │ │ │ └── BigQuerySourceDescription.ts │ │ │ ├── mongo │ │ │ │ ├── MongoConnectorDescription.ts │ │ │ │ ├── MongoRepository.ts │ │ │ │ ├── MongoSink.ts │ │ │ │ └── MongoSinkDescription.ts │ │ │ ├── mysql │ │ │ │ ├── MySqlConnectorDescription.ts │ │ │ │ ├── MySqlRepository.ts │ │ │ │ ├── MySqlSink.ts │ │ │ │ └── MySqlSinkDescription.ts │ │ │ ├── postgres │ │ │ │ ├── PostgresConnectorDescription.ts │ │ │ │ ├── PostgresRepository.ts │ │ │ │ ├── PostgresSink.ts │ │ │ │ ├── PostgresSinkDescription.ts │ │ │ │ ├── PostgresSource.ts │ │ │ │ └── PostgresSourceDescription.ts │ │ │ └── redshift │ │ │ │ ├── RedshiftConnector.ts │ │ │ │ ├── RedshiftConnectorDescription.ts │ │ │ │ ├── RedshiftSink.ts │ │ │ │ ├── RedshiftSinkDescription.ts │ │ │ │ ├── RedshiftSource.ts │ │ │ │ └── RedshiftSourceDescription.ts │ │ ├── decodable │ │ │ ├── DecodableConnector.ts │ │ │ ├── DecodableConnectorDescription.ts │ │ │ ├── DecodableSink.spec.ts │ │ │ ├── DecodableSink.ts │ │ │ └── DecodableSinkDescription.ts │ │ ├── event-source │ │ │ ├── EventSourceConnector.ts │ │ │ ├── EventSourceConnectorDescription.ts │ │ │ ├── EventSourceSource.ts │ │ │ └── EventSourceSourceDescription.ts │ │ ├── file-based │ │ │ ├── AbstractFileSink.ts │ │ │ ├── AbstractFileStreamSource.ts │ │ │ ├── datapm-registry │ │ │ │ ├── DataPMConnectorDescription.ts │ │ │ │ ├── DataPMRepository.ts │ │ │ │ ├── DataPMSink.ts │ │ │ │ ├── DataPMSinkDescription.ts │ │ │ │ ├── DataPMSource.ts │ │ │ │ └── DataPMSourceDescription.ts │ │ │ ├── google-sheet │ │ │ │ ├── GoogleSheetConnectorDescription.ts │ │ │ │ ├── GoogleSheetRepository.ts │ │ │ │ ├── GoogleSheetSource.ts │ │ │ │ └── GoogleSheetSourceDescription.ts │ │ │ ├── http │ │ │ │ ├── HTTPConnectorDescription.ts │ │ │ │ ├── HTTPRepository.ts │ │ │ │ ├── HTTPSource.ts │ │ │ │ └── HTTPSourceDescription.ts │ │ │ ├── local-file │ │ │ │ ├── LocalFileConnectorDescription.ts │ │ │ │ ├── LocalFileRepository.ts │ │ │ │ ├── LocalFileSink.ts │ │ │ │ ├── LocalFileSinkDescription.ts │ │ │ │ ├── LocalFileSource.ts │ │ │ │ └── LocalFileSourceDescription.ts │ │ │ ├── parser │ │ │ │ ├── AVROParser.ts │ │ │ │ ├── AVROParserDescription.ts │ │ │ │ ├── AbstractArchiveParser.ts │ │ │ │ ├── AbstractPassthroughParser.ts │ │ │ │ ├── BZip2Parser.ts │ │ │ │ ├── BZip2ParserDescription.ts │ │ │ │ ├── CSVParser.ts │ │ │ │ ├── CSVParserDescription.ts │ │ │ │ ├── GZipParser.ts │ │ │ │ ├── GZipParserDescription.ts │ │ │ │ ├── JSONParser.ts │ │ │ │ ├── JSONParserDescription.ts │ │ │ │ ├── Parser.ts │ │ │ │ ├── ParserUtil.ts │ │ │ │ ├── TARParser.ts │ │ │ │ ├── TARParserDescription.ts │ │ │ │ ├── XLSXParser.ts │ │ │ │ ├── XLSXParserDescription.ts │ │ │ │ ├── XMLParser.ts │ │ │ │ ├── XMLParserDescription.ts │ │ │ │ ├── ZIPParser.ts │ │ │ │ └── ZIPParserDescription.ts │ │ │ ├── s3 │ │ │ │ ├── S3ConnectorDescription.ts │ │ │ │ ├── S3Repository.ts │ │ │ │ ├── S3Sink.ts │ │ │ │ ├── S3SinkDescription.ts │ │ │ │ ├── S3Source.ts │ │ │ │ └── S3SourceDescription.ts │ │ │ ├── standard-out │ │ │ │ ├── StandardOutConnectorDescription.ts │ │ │ │ ├── StandardOutRepository.ts │ │ │ │ ├── StandardOutSink.ts │ │ │ │ └── StandardOutSinkDescription.ts │ │ │ └── writer │ │ │ │ ├── RecordSerializer.ts │ │ │ │ ├── RecordSerializerAVRO.ts │ │ │ │ ├── RecordSerializerAVRODescription.ts │ │ │ │ ├── RecordSerializerCSV.ts │ │ │ │ ├── RecordSerializerCSVDescription.ts │ │ │ │ ├── RecordSerializerJSON.ts │ │ │ │ ├── RecordSerializerJSONDescription.ts │ │ │ │ └── RecordSerializerUtil.ts │ │ ├── ftx │ │ │ ├── FTXConnector.ts │ │ │ ├── FTXConnectorDescription.ts │ │ │ ├── FTXSource.ts │ │ │ └── FTXSourceDescription.ts │ │ ├── gemini │ │ │ ├── GeminiConnector.ts │ │ │ ├── GeminiConnectorDescription.ts │ │ │ ├── GeminiSource.ts │ │ │ └── GeminiSourceDescription.ts │ │ ├── kraken │ │ │ ├── KrakenConnector.ts │ │ │ ├── KrakenConnectorDescription.ts │ │ │ ├── KrakenSource.ts │ │ │ └── KrakenSourceDescription.ts │ │ ├── stream │ │ │ ├── kafka │ │ │ │ ├── KafkaConnector.ts │ │ │ │ ├── KafkaConnectorDescription.ts │ │ │ │ ├── KafkaSink.ts │ │ │ │ └── KafkaSinkDescription.ts │ │ │ └── test │ │ │ │ ├── StreamTestConnector.ts │ │ │ │ ├── StreamTestConnectorDescription.ts │ │ │ │ ├── StreamTestSource.ts │ │ │ │ └── StreamTestSourceDescription.ts │ │ ├── timeplus │ │ │ ├── TimeplusConnector.ts │ │ │ ├── TimeplusConnectorDescription.ts │ │ │ ├── TimeplusSink.ts │ │ │ └── TimeplusSinkDescription.ts │ │ └── twitter │ │ │ ├── TwitterConnector.ts │ │ │ ├── TwitterConnectorDescription.ts │ │ │ ├── TwitterSource.ts │ │ │ └── TwitterSourceDescription.ts │ ├── content-detector │ │ ├── AgePropertyNameDetector.ts │ │ ├── ContentLabelDetector.ts │ │ ├── CreditCardNumberDetector.ts │ │ ├── DateOfBirthPropertyNameDetector.ts │ │ ├── DriversLicensePropertyNameDetector.ts │ │ ├── EmailContentDetector.ts │ │ ├── EthnicityPropertyNameDetector.ts │ │ ├── GenderPropertyNameDetector.ts │ │ ├── GeoLatitudePropertyNameDetector.ts │ │ ├── GeoLongitudePropertyNameDetector.ts │ │ ├── Ipv4AddressDetector.ts │ │ ├── Ipv6AddressDetector.ts │ │ ├── NPIPropertyNameDetector.ts │ │ ├── PassportPropertyNameDetector.ts │ │ ├── PasswordPropertyNameDetector.ts │ │ ├── PersonNameDetector.ts │ │ ├── PhoneNumberDetector.ts │ │ ├── PropertyNameDetectorBase.ts │ │ ├── RegexDetector.ts │ │ ├── SocialSecurityNumberDetector.ts │ │ └── UsernamePropertyNameDetector.ts │ ├── main.ts │ ├── task │ │ ├── AddRepositoryCredentialsJob.ts │ │ ├── AddRepositoryJob.ts │ │ ├── EditJob.ts │ │ ├── FetchPackageJob.ts │ │ ├── InfoJob.ts │ │ ├── JobContext.ts │ │ ├── PackageJob.ts │ │ ├── PublishJob.ts │ │ ├── SearchJob.ts │ │ ├── Task.ts │ │ ├── UpdateJob.ts │ │ └── UpdateRepositoryJob.ts │ ├── transforms │ │ ├── BatchingTransform.ts │ │ ├── ByteBatchingTransform.ts │ │ ├── ByteCountOffsetTransform.ts │ │ ├── InflatedByteCountTransform.ts │ │ ├── LineCountOffsetTransform.ts │ │ ├── PauseableTransform.ts │ │ ├── QuoteTransform.ts │ │ ├── RawByteCountTransform.ts │ │ ├── RecordCountOffsetTransform.ts │ │ ├── RecordStreamContextTransform.ts │ │ ├── SpigetTransform.ts │ │ ├── StatsTransform.ts │ │ └── TimeOrDeathTransform.ts │ ├── types │ │ ├── bomstrip │ │ │ └── index.d.ts │ │ ├── buffer-peek-stream │ │ │ └── index.d.ts │ │ ├── jsonstream-next │ │ │ └── index.d.ts │ │ ├── people-names │ │ │ └── index.d.ts │ │ ├── random-fruits-name │ │ │ └── index.d.ts │ │ ├── stream-fs-cache │ │ │ └── index.d.ts │ │ ├── stream-mmmagic │ │ │ └── index.d.ts │ │ ├── unbzip2-stream │ │ │ └── index.d.ts │ │ ├── why-is-node-running │ │ │ └── index.d.ts │ │ └── xml-streamer │ │ │ └── index.d.ts │ └── util │ │ ├── AsyncUtils.ts │ │ ├── AwsUtil.ts │ │ ├── ConnectionUtil.ts │ │ ├── CredentialsUtil.ts │ │ ├── DateUtil.ts │ │ ├── FakerUtil.ts │ │ ├── GoogleUtil.ts │ │ ├── IdentifierUtil.ts │ │ ├── LocalDataUtil.ts │ │ ├── Maybe.ts │ │ ├── Mutex.ts │ │ ├── NameUtil.ts │ │ ├── PackageContext.ts │ │ ├── PackageUtil.ts │ │ ├── ParsePackageIdentifierUtil.ts │ │ ├── Reference.ts │ │ ├── ReferenceUtil.ts │ │ ├── RegistryClient.ts │ │ ├── RegistryPermissions.ts │ │ ├── RegistryReferenceUtil.ts │ │ ├── SchemaUtil.ts │ │ ├── SourceInspectionUtil.ts │ │ ├── StreamToSinkUtil.ts │ │ ├── parameters │ │ ├── ParameterUtils.ts │ │ └── ParameterValidationUtils.ts │ │ └── transforms │ │ └── SinkStateWritable.ts ├── test │ ├── CSVParserTest.spec.ts │ ├── DateUtil.spec.ts │ ├── EmailContentDetector.spec.ts │ ├── IdentifierUtil.spec.ts │ ├── IdentifierUtilTest.spec.ts │ ├── LineCountOffsetTransform.spec.ts │ ├── SchemaUtil-2.spec.ts │ ├── SchemaUtil-combine.spec.ts │ ├── SchemaUtil.spec.ts │ └── StatsTransform.spec.ts └── tsconfig.json ├── client ├── .bablerc ├── .eslintignore ├── .eslintrc.yml ├── .gitignore ├── LICENSE ├── README.md ├── airports-small.json │ └── airports-small.json ├── assets │ └── datapm-logo.jpg ├── gulp │ ├── common.js │ ├── linux.js │ ├── macos.js │ └── windows.js ├── gulpfile.js ├── installers │ ├── debian │ │ ├── changelog │ │ ├── control │ │ ├── create-debian-package.sh │ │ ├── datapm-client.install │ │ ├── datapm-client.links │ │ ├── postinst │ │ └── prerm │ ├── macos │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── README.md │ │ ├── macOS-x64 │ │ │ ├── .gitignore │ │ │ ├── build-macos-x64.sh │ │ │ ├── darwin │ │ │ │ ├── Distribution │ │ │ │ ├── Resources │ │ │ │ │ ├── LICENSE.txt │ │ │ │ │ ├── banner.png │ │ │ │ │ ├── conclusion.html │ │ │ │ │ ├── uninstall.sh │ │ │ │ │ └── welcome.html │ │ │ │ └── scripts │ │ │ │ │ └── postinstall │ │ │ ├── macos-runtime-entitlements.plist │ │ │ └── utils │ │ │ │ └── ascii_art.txt │ │ ├── sign-apps.sh │ │ └── utils │ │ │ └── apple-logo-animation.gif │ ├── redhat │ │ ├── create-redhat-package.sh │ │ └── datapm-client-x64.spec │ └── windows │ │ ├── README.md │ │ └── appxmanifest.xml ├── npm-shrinkwrap.json ├── package.json ├── src │ ├── command │ │ ├── CatalogsCommand.ts │ │ ├── CatalogsCommandModule.ts │ │ ├── Command.ts │ │ ├── CommandTaskUtil.ts │ │ ├── CompareCommand.ts │ │ ├── CompareCommandModule.ts │ │ ├── ConfigurationCommand.ts │ │ ├── CopyPackageCommand.ts │ │ ├── CopyPackageCommandModule.ts │ │ ├── EditCommand.ts │ │ ├── EditCommandModule.ts │ │ ├── FallbackCommand.ts │ │ ├── FetchCommand.ts │ │ ├── FetchCommandModule.ts │ │ ├── InfoCommand.ts │ │ ├── InfoCommandModule.ts │ │ ├── PackageCommand.ts │ │ ├── PackageCommandModule.ts │ │ ├── PublishPackageCommand.ts │ │ ├── PublishPackageCommandModule.ts │ │ ├── RegistryCommand.ts │ │ ├── RegistryCommandModule.ts │ │ ├── RepositoryCommand.ts │ │ ├── RepositoryCommandModule.ts │ │ ├── SearchCommand.ts │ │ ├── SearchCommandModule.ts │ │ ├── UpdateCommand.ts │ │ └── UpdateCommandModule.ts │ ├── main.ts │ └── util │ │ ├── CLIParameterUtils.ts │ │ ├── ConfigUtil.ts │ │ ├── DatapmVersionUtil.ts │ │ ├── DefaultParameterOptions.ts │ │ ├── GetPackageUtil.ts │ │ ├── LocalPackageFileContext.ts │ │ ├── OraQuiet.ts │ │ ├── RegistryClient.ts │ │ └── VersionCheckUtil.ts ├── test │ ├── extended │ │ ├── test-big-query-sink.ts │ │ ├── test-big-query-source.ts │ │ ├── test-redshift-sink.ts_ │ │ ├── test-redshift-source.ts_ │ │ ├── test-s3-sink.ts │ │ └── test-s3-source.ts │ ├── integration │ │ ├── setup.ts │ │ ├── test-binance-source.ts │ │ ├── test-catalogs-command.ts │ │ ├── test-coinbase-source-matches.ts │ │ ├── test-coinbase-source-ticker.ts │ │ ├── test-compare-command.ts │ │ ├── test-configuration-command.ts │ │ ├── test-content-detection.ts │ │ ├── test-csv-offset-update.ts │ │ ├── test-edit-command.ts │ │ ├── test-fallback-command.ts │ │ ├── test-fetch-cli-options.ts │ │ ├── test-fetch-command.ts │ │ ├── test-fetch-source-parameters.ts │ │ ├── test-ftx-source-ticker.ts │ │ ├── test-ftx-source-trades.ts │ │ ├── test-gemini-source-ticker.ts │ │ ├── test-googlesheet-source.ts │ │ ├── test-info-command.ts │ │ ├── test-kraken-source-spread.ts │ │ ├── test-kraken-source-ticker.ts │ │ ├── test-mongo-sink.ts │ │ ├── test-mysql-sink.ts │ │ ├── test-package-command.ts │ │ ├── test-package-compressed.ts │ │ ├── test-package-derived-from.ts │ │ ├── test-postgres-sink.ts │ │ ├── test-postgres-source.ts │ │ ├── test-publish-data-append-log.ts │ │ ├── test-publish-data-batch.ts │ │ ├── test-publish-package-command.ts │ │ ├── test-registry-command.ts │ │ ├── test-registry-login-logout-commands.ts │ │ ├── test-repository-command.ts │ │ ├── test-search-command.ts │ │ ├── test-sink-avro.ts │ │ ├── test-sink-csv.ts │ │ ├── test-sink-json.ts │ │ ├── test-sink-kafka.ts │ │ ├── test-source-avro.ts │ │ ├── test-source-csv.ts │ │ ├── test-source-json.ts │ │ ├── test-source-multiple-files.ts │ │ ├── test-source-tar.ts │ │ ├── test-source-xlsx.ts │ │ ├── test-source-xml.ts │ │ ├── test-source-zip.ts │ │ ├── test-standard-out-sink.ts │ │ ├── test-stream-source.ts │ │ ├── test-update-command.ts │ │ └── test-utils.ts │ ├── packages │ │ ├── coinbase-btc-usd.LICENSE.md │ │ ├── coinbase-btc-usd.README.md │ │ ├── coinbase-btc-usd.datapm.json │ │ ├── us-federal-it-standards.README.md │ │ ├── us-federal-it-standards.datapm.json │ │ ├── us-federal-websites.datapm.json │ │ ├── us-state-codes.datapm.json │ │ └── us-websites-2.datapm.json │ ├── sources │ │ ├── airports-small.csv │ │ ├── all-types.csv │ │ ├── business-confidence-index.csv │ │ ├── coinbaseUSD-small.csv │ │ ├── content-detection.csv │ │ ├── countries-v1.csv │ │ ├── countries-v2.csv │ │ ├── country-currencies.xml │ │ ├── covid-02-01-2020.avro │ │ ├── covid-02-01-2020.csv │ │ ├── covid-03-01-2020.csv │ │ ├── daily_prices.json │ │ ├── legislators.csv │ │ ├── non-profits-1.csv │ │ ├── non-profits-1.zip │ │ ├── non-profits-2-4.zip │ │ ├── non-profits-2.csv │ │ ├── non-profits-3.csv │ │ ├── non-profits-4.csv │ │ ├── object-test.json │ │ ├── sea-level_fig-1.csv │ │ ├── source.tar │ │ ├── source.zip │ │ ├── state-codes.csv │ │ ├── state-codes.csv.bz2 │ │ ├── state-codes.csv.gzip │ │ ├── test-date-data.csv │ │ ├── us-covid.csv │ │ ├── us-covid.xlsx │ │ └── weird-headers.csv │ └── test-data-server.ts └── tsconfig.json ├── docker ├── Docker-env ├── Dockerfile ├── Dockerfile-ci ├── Dockerfile-client ├── docker-compose-local-build.yml ├── docker-compose-local-dev.yml ├── docker-compose.yml └── init-database.sh ├── docs ├── .dockerignore ├── .gitignore ├── Dockerfile ├── docker-compose.yml ├── docs │ ├── about.md │ ├── access-control.md │ ├── command-line-client.md │ ├── concepts.md │ ├── connectors.md │ ├── devops.md │ ├── find-data.md │ ├── license.md │ ├── package-files.md │ ├── private-docker-compose.md │ ├── private-google-cloud-run.md │ ├── private-registry.md │ ├── publish-data.md │ ├── quick-start.md │ ├── registry-api.md │ ├── unclaimed-listings.md │ └── use-case-catalog-data.md └── website │ ├── .gitignore │ ├── README.md │ ├── core │ └── Footer.js │ ├── gulpfile.js │ ├── package-lock.json │ ├── package.json │ ├── pages │ └── en │ │ ├── help.js │ │ └── users.js │ ├── sidebars.json │ ├── siteConfig.js │ └── static │ ├── css │ ├── colors.css │ └── custom.css │ ├── font │ ├── LICENSE.txt │ └── static │ │ ├── Roboto-Black.ttf │ │ ├── Roboto-BlackItalic.ttf │ │ ├── Roboto-Bold.ttf │ │ ├── Roboto-BoldItalic.ttf │ │ ├── Roboto-Italic.ttf │ │ ├── Roboto-Light.ttf │ │ ├── Roboto-LightItalic.ttf │ │ ├── Roboto-Medium.ttf │ │ ├── Roboto-MediumItalic.ttf │ │ ├── Roboto-Regular.ttf │ │ ├── Roboto-Thin.ttf │ │ └── Roboto-ThinItalic.ttf │ ├── img │ ├── favicon.ico │ ├── oss_logo.png │ ├── undraw_code_review.svg │ ├── undraw_monitor.svg │ ├── undraw_note_list.svg │ ├── undraw_online.svg │ ├── undraw_open_source.svg │ ├── undraw_operating_system.svg │ ├── undraw_react.svg │ ├── undraw_tweetstorm.svg │ └── undraw_youtube_tutorial.svg │ ├── index.html │ ├── load-theme-options.js │ ├── test-data │ └── state-codes.csv │ └── test-packagefiles │ ├── country-year-gdp.datapm.json │ ├── us-congressional-legislators.datapm.json │ └── us-state-abbreviation-codes.datapm.json ├── frontend ├── .browserslistrc ├── .editorconfig ├── .gitignore ├── .prettierrc.yaml ├── README.md ├── angular.json ├── codegen.yml ├── e2e │ ├── protractor.conf.js │ ├── src │ │ ├── app.e2e-spec.ts │ │ └── app.po.ts │ └── tsconfig.json ├── gulpfile.js ├── karma.conf.js ├── package-lock.json ├── package.json ├── proxy.conf.js ├── proxy.prod.conf.js ├── proxy.test.conf.json ├── src │ ├── app │ │ ├── app-routing.module.ts │ │ ├── app.component.html │ │ ├── app.component.scss │ │ ├── app.component.spec.ts │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── auth-callbacks │ │ │ ├── accept-invite │ │ │ │ ├── accept-invite.component.html │ │ │ │ ├── accept-invite.component.scss │ │ │ │ └── accept-invite.component.ts │ │ │ ├── auth-callbacks-routing.module.ts │ │ │ ├── auth-callbacks.module.ts │ │ │ ├── password-recovery │ │ │ │ ├── password-recovery.component.html │ │ │ │ ├── password-recovery.component.scss │ │ │ │ ├── password-recovery.component.spec.ts │ │ │ │ └── password-recovery.component.ts │ │ │ └── verify-email │ │ │ │ ├── verify-email.component.html │ │ │ │ ├── verify-email.component.scss │ │ │ │ ├── verify-email.component.spec.ts │ │ │ │ └── verify-email.component.ts │ │ ├── catalog │ │ │ ├── add-user │ │ │ │ ├── add-user.component.html │ │ │ │ ├── add-user.component.scss │ │ │ │ ├── add-user.component.spec.ts │ │ │ │ └── add-user.component.ts │ │ │ ├── catalog-details │ │ │ │ ├── catalog-details.component.html │ │ │ │ ├── catalog-details.component.scss │ │ │ │ ├── catalog-details.component.spec.ts │ │ │ │ ├── catalog-details.component.ts │ │ │ │ └── catalog-followers │ │ │ │ │ ├── catalog-followers.component.html │ │ │ │ │ └── catalog-followers.component.ts │ │ │ ├── catalog-permissions │ │ │ │ ├── catalog-permissions.component.html │ │ │ │ ├── catalog-permissions.component.scss │ │ │ │ ├── catalog-permissions.component.spec.ts │ │ │ │ └── catalog-permissions.component.ts │ │ │ ├── catalog-routing.module.ts │ │ │ ├── catalog.module.ts │ │ │ ├── catalog │ │ │ │ ├── catalog.component.html │ │ │ │ ├── catalog.component.scss │ │ │ │ ├── catalog.component.spec.ts │ │ │ │ └── catalog.component.ts │ │ │ └── user-details-page │ │ │ │ ├── user-details-page.component.html │ │ │ │ ├── user-details-page.component.scss │ │ │ │ ├── user-details-page.component.spec.ts │ │ │ │ └── user-details-page.component.ts │ │ ├── collection-details │ │ │ ├── add-group-collection-permissions │ │ │ │ ├── add-group-collection-permissions.component.html │ │ │ │ ├── add-group-collection-permissions.component.scss │ │ │ │ ├── add-group-collection-permissions.component.spec.ts │ │ │ │ └── add-group-collection-permissions.component.ts │ │ │ ├── add-package │ │ │ │ ├── add-package.component.html │ │ │ │ ├── add-package.component.scss │ │ │ │ ├── add-package.component.spec.ts │ │ │ │ └── add-package.component.ts │ │ │ ├── add-user │ │ │ │ ├── add-user.component.html │ │ │ │ ├── add-user.component.scss │ │ │ │ ├── add-user.component.spec.ts │ │ │ │ └── add-user.component.ts │ │ │ ├── collection-details-routing.module.ts │ │ │ ├── collection-details.module.ts │ │ │ ├── collection-details │ │ │ │ ├── collection-details.component.html │ │ │ │ ├── collection-details.component.scss │ │ │ │ ├── collection-details.component.spec.ts │ │ │ │ ├── collection-details.component.ts │ │ │ │ ├── collection-followers │ │ │ │ │ ├── collection-followers.component.html │ │ │ │ │ └── collection-followers.component.ts │ │ │ │ └── mock-data.ts │ │ │ └── collection-permissions │ │ │ │ ├── collection-permissions.component.html │ │ │ │ ├── collection-permissions.component.scss │ │ │ │ ├── collection-permissions.component.spec.ts │ │ │ │ └── collection-permissions.component.ts │ │ ├── downloads │ │ │ ├── downloads-routing.module.ts │ │ │ ├── downloads.component.html │ │ │ ├── downloads.component.scss │ │ │ ├── downloads.component.spec.ts │ │ │ ├── downloads.component.ts │ │ │ └── downloads.module.ts │ │ ├── graphql.module.ts │ │ ├── group │ │ │ ├── add-group-catalog-permissions │ │ │ │ ├── add-group-catalog-permissions.component.html │ │ │ │ ├── add-group-catalog-permissions.component.scss │ │ │ │ ├── add-group-catalog-permissions.component.spec.ts │ │ │ │ └── add-group-catalog-permissions.component.ts │ │ │ ├── add-group-package-permissions │ │ │ │ ├── add-group-package-permissions.component.html │ │ │ │ ├── add-group-package-permissions.component.scss │ │ │ │ ├── add-group-package-permissions.component.spec.ts │ │ │ │ └── add-group-package-permissions.component.ts │ │ │ ├── add-user │ │ │ │ ├── add-user.component.html │ │ │ │ ├── add-user.component.scss │ │ │ │ ├── add-user.component.spec.ts │ │ │ │ └── add-user.component.ts │ │ │ ├── group-catalog │ │ │ │ ├── group-catalog.component.html │ │ │ │ ├── group-catalog.component.scss │ │ │ │ ├── group-catalog.component.spec.ts │ │ │ │ └── group-catalog.component.ts │ │ │ ├── group-collection │ │ │ │ ├── group-collection.component.html │ │ │ │ ├── group-collection.component.scss │ │ │ │ ├── group-collection.component.spec.ts │ │ │ │ └── group-collection.component.ts │ │ │ ├── group-details │ │ │ │ ├── group-details.component.html │ │ │ │ ├── group-details.component.scss │ │ │ │ ├── group-details.component.spec.ts │ │ │ │ └── group-details.component.ts │ │ │ ├── group-manage │ │ │ │ ├── group-manage.component.html │ │ │ │ ├── group-manage.component.scss │ │ │ │ ├── group-manage.component.spec.ts │ │ │ │ └── group-manage.component.ts │ │ │ ├── group-packages │ │ │ │ ├── group-packages.component.html │ │ │ │ ├── group-packages.component.scss │ │ │ │ ├── group-packages.component.spec.ts │ │ │ │ └── group-packages.component.ts │ │ │ ├── group-permissions │ │ │ │ ├── group-permissions.component.html │ │ │ │ ├── group-permissions.component.scss │ │ │ │ ├── group-permissions.component.spec.ts │ │ │ │ └── group-permissions.component.ts │ │ │ ├── group-routing.module.ts │ │ │ └── group.module.ts │ │ ├── helpers │ │ │ ├── IdentifierHelper.ts │ │ │ ├── RegistryAccessHelper.spec.ts │ │ │ ├── RegistryAccessHelper.ts │ │ │ ├── TimeUtil.ts │ │ │ ├── auth-guard.ts │ │ │ ├── utils.ts │ │ │ └── validators.ts │ │ ├── home │ │ │ ├── admin-dashboard │ │ │ │ ├── admin-dashboard.component.html │ │ │ │ ├── admin-dashboard.component.scss │ │ │ │ ├── admin-dashboard.component.ts │ │ │ │ ├── groups │ │ │ │ │ ├── admin-status-confirmation │ │ │ │ │ │ ├── admin-status-confirmation.component.html │ │ │ │ │ │ ├── admin-status-confirmation.component.scss │ │ │ │ │ │ ├── admin-status-confirmation.component.spec.ts │ │ │ │ │ │ └── admin-status-confirmation.component.ts │ │ │ │ │ ├── groups.component.html │ │ │ │ │ ├── groups.component.scss │ │ │ │ │ └── groups.component.ts │ │ │ │ ├── platform-settings │ │ │ │ │ ├── platform-settings.component.html │ │ │ │ │ ├── platform-settings.component.scss │ │ │ │ │ ├── platform-settings.component.spec.ts │ │ │ │ │ └── platform-settings.component.ts │ │ │ │ └── users │ │ │ │ │ ├── admin-status-confirmation │ │ │ │ │ ├── admin-status-confirmation.component.html │ │ │ │ │ ├── admin-status-confirmation.component.scss │ │ │ │ │ ├── admin-status-confirmation.component.spec.ts │ │ │ │ │ └── admin-status-confirmation.component.ts │ │ │ │ │ ├── users.component.html │ │ │ │ │ ├── users.component.scss │ │ │ │ │ └── users.component.ts │ │ │ ├── following │ │ │ │ ├── following.component.html │ │ │ │ ├── following.component.scss │ │ │ │ └── following.component.ts │ │ │ ├── home-routing.module.ts │ │ │ ├── home.module.ts │ │ │ ├── homepage │ │ │ │ ├── homepage.component.html │ │ │ │ ├── homepage.component.scss │ │ │ │ ├── homepage.component.spec.ts │ │ │ │ └── homepage.component.ts │ │ │ ├── latest │ │ │ │ ├── latest.component.html │ │ │ │ ├── latest.component.spec.ts │ │ │ │ └── latest.component.ts │ │ │ ├── recently-viewed │ │ │ │ ├── recently-viewed.component.html │ │ │ │ ├── recently-viewed.component.scss │ │ │ │ ├── recently-viewed.component.spec.ts │ │ │ │ └── recently-viewed.component.ts │ │ │ └── trending │ │ │ │ ├── trending.component.html │ │ │ │ ├── trending.component.scss │ │ │ │ ├── trending.component.spec.ts │ │ │ │ └── trending.component.ts │ │ ├── imported │ │ │ ├── builder-io-component │ │ │ │ ├── builder-io-renderer │ │ │ │ │ ├── builder-io-renderer.component.html │ │ │ │ │ ├── builder-io-renderer.component.scss │ │ │ │ │ └── builder-io-renderer.component.ts │ │ │ │ ├── builder-io.component.html │ │ │ │ ├── builder-io.component.scss │ │ │ │ └── builder-io.component.ts │ │ │ ├── imported.module.ts │ │ │ ├── resource-importer.service.ts │ │ │ └── safe-html.pipe.ts │ │ ├── json-typings.d.ts │ │ ├── login-container │ │ │ ├── login-container-routing.module.ts │ │ │ ├── login-container.component.html │ │ │ ├── login-container.component.scss │ │ │ ├── login-container.component.spec.ts │ │ │ ├── login-container.component.ts │ │ │ └── login-container.module.ts │ │ ├── markdown-options.ts │ │ ├── models │ │ │ ├── page-state.ts │ │ │ └── tab.model.ts │ │ ├── package │ │ │ ├── components │ │ │ │ ├── add-user │ │ │ │ │ ├── add-user.component.html │ │ │ │ │ ├── add-user.component.scss │ │ │ │ │ ├── add-user.component.spec.ts │ │ │ │ │ └── add-user.component.ts │ │ │ │ ├── edit-package-markdown │ │ │ │ │ ├── edit-package-markdown.component.html │ │ │ │ │ ├── edit-package-markdown.component.scss │ │ │ │ │ ├── edit-package-markdown.component.spec.ts │ │ │ │ │ └── edit-package-markdown.component.ts │ │ │ │ ├── package-description │ │ │ │ │ ├── package-description.component.html │ │ │ │ │ ├── package-description.component.scss │ │ │ │ │ ├── package-description.component.spec.ts │ │ │ │ │ └── package-description.component.ts │ │ │ │ ├── package-followers │ │ │ │ │ ├── package-followers.component.html │ │ │ │ │ └── package-followers.component.ts │ │ │ │ ├── package-info │ │ │ │ │ ├── Inspecting public_150k_plus_220703.csv.md │ │ │ │ │ ├── download-package │ │ │ │ │ │ ├── client-wizard │ │ │ │ │ │ │ ├── client-wizard.component.html │ │ │ │ │ │ │ ├── client-wizard.component.scss │ │ │ │ │ │ │ ├── client-wizard.component.spec.ts │ │ │ │ │ │ │ └── client-wizard.component.ts │ │ │ │ │ │ ├── download-package.component.html │ │ │ │ │ │ ├── download-package.component.scss │ │ │ │ │ │ ├── download-package.component.spec.ts │ │ │ │ │ │ └── download-package.component.ts │ │ │ │ │ ├── edit-website-dialog │ │ │ │ │ │ ├── edit-website-dialog.component.html │ │ │ │ │ │ ├── edit-website-dialog.component.scss │ │ │ │ │ │ ├── edit-website-dialog.component.spec.ts │ │ │ │ │ │ └── edit-website-dialog.component.ts │ │ │ │ │ ├── package-info.component.html │ │ │ │ │ ├── package-info.component.scss │ │ │ │ │ ├── package-info.component.spec.ts │ │ │ │ │ └── package-info.component.ts │ │ │ │ ├── package-issues │ │ │ │ │ ├── create-package-issue │ │ │ │ │ │ ├── create-package-issue.component.html │ │ │ │ │ │ ├── create-package-issue.component.scss │ │ │ │ │ │ ├── create-package-issue.component.spec.ts │ │ │ │ │ │ └── create-package-issue.component.ts │ │ │ │ │ ├── package-issues-detail │ │ │ │ │ │ ├── package-issues-detail.component.html │ │ │ │ │ │ ├── package-issues-detail.component.scss │ │ │ │ │ │ ├── package-issues-detail.component.spec.ts │ │ │ │ │ │ └── package-issues-detail.component.ts │ │ │ │ │ ├── package-issues.component.html │ │ │ │ │ ├── package-issues.component.scss │ │ │ │ │ └── package-issues.component.ts │ │ │ │ ├── package-permission │ │ │ │ │ ├── package-permission.component.html │ │ │ │ │ ├── package-permission.component.scss │ │ │ │ │ ├── package-permission.component.spec.ts │ │ │ │ │ └── package-permission.component.ts │ │ │ │ ├── package-samples │ │ │ │ │ ├── package-samples.component.html │ │ │ │ │ ├── package-samples.component.scss │ │ │ │ │ ├── package-samples.component.ts │ │ │ │ │ ├── samples-fullscreen-dailog.component.html │ │ │ │ │ ├── samples-fullscreen-dialog.component.scss │ │ │ │ │ ├── samples-fullscreen-dialog.component.ts │ │ │ │ │ ├── samples.component.html │ │ │ │ │ ├── samples.component.scss │ │ │ │ │ └── samples.component.ts │ │ │ │ ├── package-schema │ │ │ │ │ ├── edit-property-dialog │ │ │ │ │ │ ├── edit-property-dialog.component.html │ │ │ │ │ │ ├── edit-property-dialog.component.scss │ │ │ │ │ │ ├── edit-property-dialog.component.spec.ts │ │ │ │ │ │ └── edit-property-dialog.component.ts │ │ │ │ │ ├── package-schema.component.html │ │ │ │ │ ├── package-schema.component.scss │ │ │ │ │ ├── package-schema.component.spec.ts │ │ │ │ │ └── package-schema.component.ts │ │ │ │ ├── package-version │ │ │ │ │ ├── package-version.component.html │ │ │ │ │ ├── package-version.component.scss │ │ │ │ │ ├── package-version.component.ts │ │ │ │ │ ├── version-change-label-util.ts │ │ │ │ │ └── version-comparison-modal │ │ │ │ │ │ ├── version-comparison-modal.component.html │ │ │ │ │ │ ├── version-comparison-modal.component.scss │ │ │ │ │ │ ├── version-comparison-modal.component.ts │ │ │ │ │ │ └── version-comparison-model.ts │ │ │ │ └── package │ │ │ │ │ ├── package-deletion-confirmation │ │ │ │ │ ├── package-deletion-confirmation.component.html │ │ │ │ │ ├── package-deletion-confirmation.component.scss │ │ │ │ │ └── package-deletion-confirmation.component.ts │ │ │ │ │ ├── package.component.html │ │ │ │ │ ├── package.component.scss │ │ │ │ │ ├── package.component.spec.ts │ │ │ │ │ └── package.component.ts │ │ │ ├── package-routing.module.ts │ │ │ ├── package.module.ts │ │ │ ├── pipes │ │ │ │ ├── package-file-update-method.pipe.ts │ │ │ │ ├── package-size.pipe.spec.ts │ │ │ │ ├── package-size.pipe.ts │ │ │ │ ├── schema-properties.pipe.spec.ts │ │ │ │ ├── schema-properties.pipe.ts │ │ │ │ ├── update-method.pipe.ts │ │ │ │ ├── version.pipe.spec.ts │ │ │ │ └── version.pipe.ts │ │ │ └── services │ │ │ │ ├── package-resolver.service.spec.ts │ │ │ │ ├── package-resolver.service.ts │ │ │ │ ├── package.service.spec.ts │ │ │ │ └── package.service.ts │ │ ├── search │ │ │ ├── search-routing.module.ts │ │ │ ├── search.component.html │ │ │ ├── search.component.scss │ │ │ ├── search.component.spec.ts │ │ │ ├── search.component.ts │ │ │ └── search.module.ts │ │ ├── services │ │ │ ├── api-key.service.ts │ │ │ ├── authentication.service.ts │ │ │ ├── capabilities-impl.service.ts │ │ │ ├── dialog │ │ │ │ ├── confirmation-dialog-config.ts │ │ │ │ ├── confirmation-dialog-data.ts │ │ │ │ ├── confirmation-dialog.service.ts │ │ │ │ ├── dialog-config.ts │ │ │ │ ├── dialog-dimensions-calculator.ts │ │ │ │ ├── dialog-dimensions.ts │ │ │ │ ├── dialog-size.ts │ │ │ │ ├── dialog-text-orientation.ts │ │ │ │ ├── dialog.service.spec.ts │ │ │ │ ├── dialog.service.ts │ │ │ │ └── user-status-change-dialog-response.ts │ │ │ ├── file.service.spec.ts │ │ │ ├── file.service.ts │ │ │ ├── image-upload.service.ts │ │ │ ├── image.service.spec.ts │ │ │ ├── image.service.ts │ │ │ ├── permissions.service.ts │ │ │ ├── snackBar.service.ts │ │ │ ├── ui-style-toggle.service.spec.ts │ │ │ └── ui-style-toggle.service.ts │ │ ├── shared │ │ │ ├── avatar │ │ │ │ ├── avatar.component.html │ │ │ │ ├── avatar.component.scss │ │ │ │ ├── avatar.component.spec.ts │ │ │ │ └── avatar.component.ts │ │ │ ├── catalog-autocomplete │ │ │ │ ├── catalog-autocomplete.component.html │ │ │ │ ├── catalog-autocomplete.component.scss │ │ │ │ ├── catalog-autocomplete.component.spec.ts │ │ │ │ └── catalog-autocomplete.component.ts │ │ │ ├── catalog-item │ │ │ │ ├── catalog-item.component.html │ │ │ │ ├── catalog-item.component.scss │ │ │ │ └── catalog-item.component.ts │ │ │ ├── collection-autocomplete │ │ │ │ ├── collection-autocomplete.component.html │ │ │ │ ├── collection-autocomplete.component.scss │ │ │ │ ├── collection-autocomplete.component.spec.ts │ │ │ │ └── collection-autocomplete.component.ts │ │ │ ├── collection-item │ │ │ │ ├── collection-item.component.html │ │ │ │ ├── collection-item.component.scss │ │ │ │ ├── collection-item.component.spec.ts │ │ │ │ └── collection-item.component.ts │ │ │ ├── command-modal │ │ │ │ ├── command-modal.component.html │ │ │ │ ├── command-modal.component.scss │ │ │ │ ├── command-modal.component.ts │ │ │ │ ├── fetch │ │ │ │ │ ├── fetch-modal.component.html │ │ │ │ │ ├── fetch-modal.component.scss │ │ │ │ │ ├── fetch-modal.component.spec.ts │ │ │ │ │ └── fetch-modal.component.ts │ │ │ │ ├── package │ │ │ │ │ ├── create-package-modal.component.html │ │ │ │ │ ├── create-package-modal.component.scss │ │ │ │ │ ├── create-package-modal.component.spec.ts │ │ │ │ │ ├── create-package-modal.component.ts │ │ │ │ │ ├── package-modal.component.html │ │ │ │ │ ├── package-modal.component.scss │ │ │ │ │ ├── package-modal.component.spec.ts │ │ │ │ │ └── package-modal.component.ts │ │ │ │ └── update │ │ │ │ │ ├── update-modal.component.html │ │ │ │ │ ├── update-modal.component.scss │ │ │ │ │ ├── update-modal.component.spec.ts │ │ │ │ │ └── update-modal.component.ts │ │ │ ├── confirmation-dialog │ │ │ │ ├── confirmation-dialog.component.html │ │ │ │ ├── confirmation-dialog.component.scss │ │ │ │ ├── confirmation-dialog.component.spec.ts │ │ │ │ └── confirmation-dialog.component.ts │ │ │ ├── cover │ │ │ │ ├── cover.component.html │ │ │ │ ├── cover.component.scss │ │ │ │ ├── cover.component.spec.ts │ │ │ │ └── cover.component.ts │ │ │ ├── create-catalog │ │ │ │ ├── create-catalog.component.html │ │ │ │ ├── create-catalog.component.scss │ │ │ │ ├── create-catalog.component.spec.ts │ │ │ │ └── create-catalog.component.ts │ │ │ ├── create-collection │ │ │ │ ├── create-collection.component.html │ │ │ │ ├── create-collection.component.scss │ │ │ │ ├── create-collection.component.spec.ts │ │ │ │ └── create-collection.component.ts │ │ │ ├── create-group │ │ │ │ ├── create-group.component.html │ │ │ │ ├── create-group.component.scss │ │ │ │ ├── create-group.component.spec.ts │ │ │ │ └── create-group.component.ts │ │ │ ├── delete-catalog │ │ │ │ ├── delete-catalog.component.html │ │ │ │ ├── delete-catalog.component.scss │ │ │ │ ├── delete-catalog.component.spec.ts │ │ │ │ └── delete-catalog.component.ts │ │ │ ├── delete-collection │ │ │ │ ├── delete-collection.component.html │ │ │ │ ├── delete-collection.component.scss │ │ │ │ ├── delete-collection.component.spec.ts │ │ │ │ └── delete-collection.component.ts │ │ │ ├── delete-group │ │ │ │ ├── delete-group.component.html │ │ │ │ ├── delete-group.component.scss │ │ │ │ ├── delete-group.component.spec.ts │ │ │ │ └── delete-group.component.ts │ │ │ ├── delete-package │ │ │ │ ├── delete-package.component.html │ │ │ │ ├── delete-package.component.scss │ │ │ │ ├── delete-package.component.spec.ts │ │ │ │ └── delete-package.component.ts │ │ │ ├── dialogs │ │ │ │ ├── fancy-confirmation-dialog │ │ │ │ │ ├── fancy-confirmation-dialog.component.html │ │ │ │ │ ├── fancy-confirmation-dialog.component.scss │ │ │ │ │ └── fancy-confirmation-dialog.component.ts │ │ │ │ ├── follow-dialog │ │ │ │ │ ├── follow-dialog.component.html │ │ │ │ │ ├── follow-dialog.component.scss │ │ │ │ │ ├── follow-dialog.component.spec.ts │ │ │ │ │ └── follow-dialog.component.ts │ │ │ │ ├── share-dialog │ │ │ │ │ ├── share-dialog.component.html │ │ │ │ │ ├── share-dialog.component.scss │ │ │ │ │ ├── share-dialog.component.spec.ts │ │ │ │ │ └── share-dialog.component.ts │ │ │ │ └── user-status-change-confirmation-dialog │ │ │ │ │ ├── user-status-change-confirmation-dialog.component.html │ │ │ │ │ ├── user-status-change-confirmation-dialog.component.scss │ │ │ │ │ └── user-status-change-confirmation-dialog.component.ts │ │ │ ├── edit-catalog │ │ │ │ ├── edit-catalog.component.html │ │ │ │ ├── edit-catalog.component.scss │ │ │ │ ├── edit-catalog.component.spec.ts │ │ │ │ └── edit-catalog.component.ts │ │ │ ├── edit-collection │ │ │ │ ├── edit-collection.component.html │ │ │ │ ├── edit-collection.component.scss │ │ │ │ ├── edit-collection.component.spec.ts │ │ │ │ └── edit-collection.component.ts │ │ │ ├── edit-group │ │ │ │ ├── edit-group.component.html │ │ │ │ ├── edit-group.component.scss │ │ │ │ ├── edit-group.component.spec.ts │ │ │ │ └── edit-group.component.ts │ │ │ ├── followers │ │ │ │ ├── followers.component.html │ │ │ │ ├── followers.component.scss │ │ │ │ ├── followers.component.spec.ts │ │ │ │ └── followers.component.ts │ │ │ ├── footer │ │ │ │ ├── footer.component.html │ │ │ │ ├── footer.component.scss │ │ │ │ ├── footer.component.spec.ts │ │ │ │ └── footer.component.ts │ │ │ ├── header │ │ │ │ ├── forgot-password-dialog │ │ │ │ │ ├── forgot-password-dialog.component.html │ │ │ │ │ ├── forgot-password-dialog.component.scss │ │ │ │ │ ├── forgot-password-dialog.component.spec.ts │ │ │ │ │ └── forgot-password-dialog.component.ts │ │ │ │ ├── header.component.html │ │ │ │ ├── header.component.scss │ │ │ │ ├── header.component.spec.ts │ │ │ │ ├── header.component.ts │ │ │ │ ├── login-dialog │ │ │ │ │ ├── login-dialog.component.html │ │ │ │ │ ├── login-dialog.component.scss │ │ │ │ │ ├── login-dialog.component.spec.ts │ │ │ │ │ └── login-dialog.component.ts │ │ │ │ └── sign-up-dialog │ │ │ │ │ ├── sign-up-dialog.component.html │ │ │ │ │ ├── sign-up-dialog.component.scss │ │ │ │ │ ├── sign-up-dialog.component.spec.ts │ │ │ │ │ └── sign-up-dialog.component.ts │ │ │ ├── hero │ │ │ │ ├── hero.component.html │ │ │ │ ├── hero.component.scss │ │ │ │ ├── hero.component.spec.ts │ │ │ │ └── hero.component.ts │ │ │ ├── image-upload-modal │ │ │ │ ├── image-upload-modal.component.html │ │ │ │ ├── image-upload-modal.component.scss │ │ │ │ └── image-upload-modal.component.ts │ │ │ ├── input │ │ │ │ ├── input.component.html │ │ │ │ ├── input.component.scss │ │ │ │ ├── input.component.spec.ts │ │ │ │ └── input.component.ts │ │ │ ├── markdown-editor │ │ │ │ ├── markdown-editor.component.html │ │ │ │ ├── markdown-editor.component.scss │ │ │ │ └── markdown-editor.component.ts │ │ │ ├── move-package │ │ │ │ ├── move-package.component.html │ │ │ │ ├── move-package.component.scss │ │ │ │ ├── move-package.component.spec.ts │ │ │ │ └── move-package.component.ts │ │ │ ├── package-and-collection │ │ │ │ ├── catalogs-response.ts │ │ │ │ ├── collections-horizontal-list │ │ │ │ │ ├── collections-horizontal-list.component.html │ │ │ │ │ ├── collections-horizontal-list.component.scss │ │ │ │ │ └── collections-horizontal-list.component.ts │ │ │ │ ├── collections-response.ts │ │ │ │ ├── limit-and-offset.ts │ │ │ │ ├── package-and-collection.component.html │ │ │ │ ├── package-and-collection.component.scss │ │ │ │ ├── package-and-collection.component.ts │ │ │ │ ├── packages-response.ts │ │ │ │ └── search-parameters.ts │ │ │ ├── package-autocomplete │ │ │ │ ├── package-autocomplete.component.html │ │ │ │ ├── package-autocomplete.component.scss │ │ │ │ ├── package-autocomplete.component.spec.ts │ │ │ │ └── package-autocomplete.component.ts │ │ │ ├── package-item │ │ │ │ ├── package-item.component.html │ │ │ │ ├── package-item.component.scss │ │ │ │ ├── package-item.component.spec.ts │ │ │ │ └── package-item.component.ts │ │ │ ├── pipes │ │ │ │ ├── entries.pipe.ts │ │ │ │ ├── input-error.pipe.spec.ts │ │ │ │ ├── input-error.pipe.ts │ │ │ │ ├── keys.pipe.ts │ │ │ │ ├── percent.pipe.spec.ts │ │ │ │ ├── percent.pipe.ts │ │ │ │ ├── sanitize-with-style.pipe.ts │ │ │ │ ├── sort.pipe.ts │ │ │ │ ├── time-ago.pipe.ts │ │ │ │ ├── truncate.pipe.ts │ │ │ │ ├── username.pipe.spec.ts │ │ │ │ ├── username.pipe.ts │ │ │ │ ├── values.pipe.spec.ts │ │ │ │ └── values.pipe.ts │ │ │ ├── shared.module.ts │ │ │ ├── user-details │ │ │ │ ├── edit-account-dialog │ │ │ │ │ ├── edit-account-dialog.component.html │ │ │ │ │ ├── edit-account-dialog.component.scss │ │ │ │ │ ├── edit-account-dialog.component.spec.ts │ │ │ │ │ └── edit-account-dialog.component.ts │ │ │ │ ├── edit-password-dialog │ │ │ │ │ ├── edit-password-dialog.component.html │ │ │ │ │ ├── edit-password-dialog.component.scss │ │ │ │ │ ├── edit-password-dialog.component.spec.ts │ │ │ │ │ └── edit-password-dialog.component.ts │ │ │ │ ├── few-packages-alert │ │ │ │ │ ├── few-packages-alert.component.html │ │ │ │ │ ├── few-packages-alert.component.scss │ │ │ │ │ ├── few-packages-alert.component.spec.ts │ │ │ │ │ └── few-packages-alert.component.ts │ │ │ │ ├── simple-create │ │ │ │ │ ├── simple-create.component.html │ │ │ │ │ ├── simple-create.component.scss │ │ │ │ │ ├── simple-create.component.spec.ts │ │ │ │ │ └── simple-create.component.ts │ │ │ │ ├── user-catalogs │ │ │ │ │ ├── user-catalogs.component.html │ │ │ │ │ ├── user-catalogs.component.scss │ │ │ │ │ ├── user-catalogs.component.spec.ts │ │ │ │ │ └── user-catalogs.component.ts │ │ │ │ ├── user-collections │ │ │ │ │ ├── user-collections.component.html │ │ │ │ │ ├── user-collections.component.scss │ │ │ │ │ ├── user-collections.component.spec.ts │ │ │ │ │ └── user-collections.component.ts │ │ │ │ ├── user-details-header │ │ │ │ │ ├── user-details-header.component.html │ │ │ │ │ ├── user-details-header.component.scss │ │ │ │ │ ├── user-details-header.component.spec.ts │ │ │ │ │ └── user-details-header.component.ts │ │ │ │ ├── user-details │ │ │ │ │ ├── user-details.component.html │ │ │ │ │ ├── user-details.component.scss │ │ │ │ │ ├── user-details.component.spec.ts │ │ │ │ │ └── user-details.component.ts │ │ │ │ ├── user-following │ │ │ │ │ ├── user-following.component.html │ │ │ │ │ ├── user-following.component.scss │ │ │ │ │ ├── user-following.component.ts │ │ │ │ │ └── user-type-following │ │ │ │ │ │ ├── user-type-following.component.html │ │ │ │ │ │ └── user-type-following.component.ts │ │ │ │ ├── user-groups │ │ │ │ │ ├── user-groups.component.html │ │ │ │ │ ├── user-groups.component.scss │ │ │ │ │ └── user-groups.component.ts │ │ │ │ └── user-packages │ │ │ │ │ ├── user-packages.component.html │ │ │ │ │ ├── user-packages.component.scss │ │ │ │ │ ├── user-packages.component.spec.ts │ │ │ │ │ └── user-packages.component.ts │ │ │ ├── user-invite-input │ │ │ │ ├── chip-data.ts │ │ │ │ ├── chip-state.ts │ │ │ │ ├── user-invite-input.component.html │ │ │ │ ├── user-invite-input.component.scss │ │ │ │ └── user-invite-input.component.ts │ │ │ └── user-item │ │ │ │ ├── user-item.component.html │ │ │ │ ├── user-item.component.scss │ │ │ │ ├── user-item.component.spec.ts │ │ │ │ └── user-item.component.ts │ │ └── ui.module.ts │ ├── assets │ │ ├── .gitkeep │ │ ├── dpm-logo-180x180.png │ │ ├── dpm-logo-192x192.png │ │ ├── dpm-logo-256x256.png │ │ ├── dpm-logo-512x512.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ └── images │ │ │ ├── card-img.png │ │ │ ├── cover-image.jpg │ │ │ ├── cover-image.png │ │ │ ├── envelope.png │ │ │ ├── galaxy.jpg │ │ │ ├── galaxy1.png │ │ │ ├── galaxy2.jpg │ │ │ ├── github.png │ │ │ ├── google-glass-logo.png │ │ │ ├── link-45.svg │ │ │ ├── location.png │ │ │ ├── sources │ │ │ ├── big-query.svg │ │ │ ├── csv.svg │ │ │ ├── json.svg │ │ │ ├── local-fs.svg │ │ │ ├── mariadb.svg │ │ │ ├── mongodb.svg │ │ │ ├── mysql.svg │ │ │ ├── postgresql.svg │ │ │ ├── raw_file.png │ │ │ ├── redshift.svg │ │ │ ├── s3.svg │ │ │ ├── stdout.svg │ │ │ └── xml.svg │ │ │ ├── twitter.png │ │ │ ├── user-female.jpg │ │ │ ├── user-female.png │ │ │ ├── user-male.jpg │ │ │ └── user-male2.png │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── index.html │ ├── main.ts │ ├── polyfills.ts │ ├── styles │ │ ├── _colors.scss │ │ ├── _mixins.scss │ │ ├── _theme.scss │ │ ├── _typography.scss │ │ ├── _variables.scss │ │ └── main.scss │ └── test.ts ├── tsconfig.app.json ├── tsconfig.base.json ├── tsconfig.json ├── tsconfig.spec.json ├── tslint.json └── typescript-typedefs.js ├── gulpfile.js ├── lib ├── LICENSE ├── README.md ├── api-key-schema.gql ├── auth-schema.gql ├── graphql-documents │ ├── AcceptInvite.graphql │ ├── AddOrUpdateGroupToCatalog.graphql │ ├── AddOrUpdateGroupToCollection.graphql │ ├── AddOrUpdateGroupToPackage.graphql │ ├── AddOrUpdateUserToGroup.graphql │ ├── AddPackageToCollection.graphql │ ├── AdminDeleteGroup.graphql │ ├── AdminDeleteUser.graphql │ ├── AdminSearchGroups.graphql │ ├── AdminSearchUsers.graphql │ ├── AdminSetUserStatus.graphql │ ├── AutoComplete.graphql │ ├── Catalog.graphql │ ├── CatalogActivities.graphql │ ├── CatalogFollowers.graphql │ ├── CatalogFollowersCount.graphql │ ├── CatalogPackages.graphql │ ├── Collection.graphql │ ├── CollectionActivities.graphql │ ├── CollectionFollowers.graphql │ ├── CollectionFollowersCount.graphql │ ├── CollectionPackages.graphql │ ├── CollectionSlugAvailable.graphql │ ├── CreateAPIKey.graphql │ ├── CreateCatalog.graphql │ ├── CreateCollection.graphql │ ├── CreateCredential.graphql │ ├── CreateFollow.graphql │ ├── CreateGroup.graphql │ ├── CreateMe.graphql │ ├── CreatePackage.graphql │ ├── CreatePackageIssue.graphql │ ├── CreatePackageIssueComment.graphql │ ├── CreateRepository.graphql │ ├── CreateVersion.graphql │ ├── DeleteAPIKey.graphql │ ├── DeleteAllMyFollows.graphql │ ├── DeleteCatalog.graphql │ ├── DeleteCatalogAvatarImage.graphql │ ├── DeleteCollection.graphql │ ├── DeleteCredential.graphql │ ├── DeleteFollow.graphql │ ├── DeleteGroup.graphql │ ├── DeleteMe.graphql │ ├── DeletePackage.graphql │ ├── DeletePackageIssue.graphql │ ├── DeletePackageIssueComment.graphql │ ├── DeletePackageIssues.graphql │ ├── DeleteRepository.graphql │ ├── DeleteUserCatalogPermissions.graphql │ ├── DeleteUserCollectionPermissions.graphql │ ├── DeleteVersion.graphql │ ├── EmailAddressAvailable.graphql │ ├── ForgotMyPassword.graphql │ ├── GetFollow.graphql │ ├── Group.graphql │ ├── GroupsByCatalog.graphql │ ├── GroupsByCollection.graphql │ ├── GroupsByPackage.graphql │ ├── LatestCollections.graphql │ ├── LatestPackages.graphql │ ├── ListConnectors.graphql │ ├── ListRepositories.graphql │ ├── Login.graphql │ ├── Logout.graphql │ ├── Me.graphql │ ├── MovePackage.graphql │ ├── MyAPIKeys.graphql │ ├── MyActivity.graphql │ ├── MyCatalogs.graphql │ ├── MyCollections.graphql │ ├── MyFollowingActivity.graphql │ ├── MyFollows.graphql │ ├── MyGroups.graphql │ ├── MyPackages.graphql │ ├── MyRecentlyViewedCollections.graphql │ ├── MyRecentlyViewedPackages.graphql │ ├── Package.graphql │ ├── PackageActivities.graphql │ ├── PackageCollections.graphql │ ├── PackageFetched.graphql │ ├── PackageFollowers.graphql │ ├── PackageFollowersCount.graphql │ ├── PackageIssue.graphql │ ├── PackageIssueComments.graphql │ ├── PackageIssueFollowers.graphql │ ├── PackageIssueFollowersCount.graphql │ ├── PackageIssues.graphql │ ├── PackageVersionsDiff.graphql │ ├── PackageVersionsDiffs.graphql │ ├── PageContent.graphql │ ├── PlatformSettings.graphql │ ├── PublicPlatformSettingsByKey.graphql │ ├── RecoverMyPassword.graphql │ ├── RegistryStatus.graphql │ ├── RemoveGroupFromCatalog.graphql │ ├── RemoveGroupFromCollection.graphql │ ├── RemoveGroupFromPackage.graphql │ ├── RemovePackageFromCollection.graphql │ ├── RemovePackagePermissions.graphql │ ├── RemoveUserFromGroup.graphql │ ├── RunJob.graphql │ ├── SavePlatformSettings.graphql │ ├── SearchCatalogs.graphql │ ├── SearchCollections.graphql │ ├── SearchPackages.graphql │ ├── SearchUsers.graphql │ ├── SetAsAdmin.graphql │ ├── SetCatalogAvatarImage.graphql │ ├── SetCatalogCoverImage.graphql │ ├── SetCollectionCoverImage.graphql │ ├── SetGroupAsAdmin.graphql │ ├── SetMyAvatarImage.graphql │ ├── SetMyCoverImage.graphql │ ├── SetPackageCoverImage.graphql │ ├── SetPackagePermissions.graphql │ ├── SetUserCatalogPermission.graphql │ ├── SetUserCollectionPermissions.graphql │ ├── UpdateCatalog.graphql │ ├── UpdateCollection.graphql │ ├── UpdateGroup.graphql │ ├── UpdateMe.graphql │ ├── UpdateMyPassword.graphql │ ├── UpdatePackage.graphql │ ├── UpdatePackageIssue.graphql │ ├── UpdatePackageIssueComment.graphql │ ├── UpdatePackageIssueStatus.graphql │ ├── UpdatePackageIssuesStatuses.graphql │ ├── User.graphql │ ├── UserCatalogs.graphql │ ├── UserCollections.graphql │ ├── UserFollowers.graphql │ ├── UserFollowersCount.graphql │ ├── UserPackages.graphql │ ├── UsernameAvailable.graphql │ ├── UsersByCatalog.graphql │ ├── UsersByCollection.graphql │ ├── UsersByPackage.graphql │ └── VerifyEmailAddress.graphql ├── group-schema.gql ├── gulpfile.js ├── images-schema.gql ├── package-lock.json ├── package.json ├── packageFileSchema-v0.1.0.json ├── packageFileSchema-v0.2.0.json ├── packageFileSchema-v0.3.0.json ├── packageFileSchema-v0.31.5.json ├── packageFileSchema-v0.32.1.json ├── packageFileSchema-v0.4.0.json ├── packageFileSchema-v0.5.0.json ├── packageFileSchema-v0.6.0.json ├── packageFileSchema-v0.7.0.json ├── packageFileSchema-v0.8.0.json ├── packageFileSchema-v0.8.1.json ├── packageFileSchema-v0.9.0.json ├── prettierrc.yaml ├── schema.gql ├── src │ ├── APIKeyUtil.ts │ ├── CountPrecisionUtil.ts │ ├── DataHandlingUtil.ts │ ├── LibPackageVersionUtil.ts │ ├── NameUtil.ts │ ├── PackageFile-v0.1.0.ts │ ├── PackageFile-v0.2.0.ts │ ├── PackageFile-v0.3.0.ts │ ├── PackageFile-v0.31.5.ts │ ├── PackageFile-v0.32.1.ts │ ├── PackageFile-v0.4.0.ts │ ├── PackageFile-v0.5.0.ts │ ├── PackageFile-v0.6.0.ts │ ├── PackageFile-v0.7.0.ts │ ├── PackageFile-v0.8.0.ts │ ├── PackageFile-v0.8.1.ts │ ├── PackageFile-v0.9.0.ts │ ├── PackageUtil.ts │ ├── Parameter.ts │ ├── SinkState.ts │ ├── SocketUtil.ts │ ├── TimeoutPromise.ts │ ├── Validators.ts │ ├── main.ts │ └── types │ │ └── base-x │ │ └── index.d.ts ├── test │ ├── NameUtil.spec.ts │ ├── PackageComparison.spec.ts │ ├── PackageFileParse.spec.ts │ ├── PasswordValidation.spec.ts │ └── packageFiles │ │ ├── congressional-legislators.LICENSE.md │ │ ├── congressional-legislators.README.md │ │ ├── congressional-legislators.datapm.json │ │ ├── object-test.datapm.json │ │ ├── twitter-sample-1.0.0.datapm.json │ │ ├── twitter-sample.LICENSE.md │ │ └── twitter-sample.README.md ├── tsconfig.json ├── tslint.json └── user-schema.gql ├── package-lock.json ├── package.json ├── terraform ├── .gitignore ├── backend-example.config ├── environment-example.tfvars ├── environments │ ├── production.config │ ├── production.tfvars │ ├── test.config │ └── test.tfvars └── main.tf ├── test └── smoke-test-setup.ts └── tsconfig.json /.dockerignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | node_modules 3 | npm-debug.log 4 | .git 5 | .terraform 6 | client/installers/macos/macOS-x64/application/* 7 | client/pkg-* 8 | ./dist 9 | backend/tmp-registry-server-* 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # TODO Needs Linting 2 | frontend 3 | docs 4 | 5 | # Has its own linting 6 | client 7 | 8 | # Never Lint 9 | node_modules 10 | dist 11 | lib/node_modules 12 | lib/dist 13 | 14 | client-lib/node_modules 15 | client-lib/dist 16 | client-lib/src/generated 17 | client-lib/test/integration/registry-client.ts 18 | 19 | backend/dist 20 | backend/src/generated 21 | backend/tmp-* 22 | backend/node_modules 23 | backend/test/integration/registry-client.ts 24 | backend/gulpfile.js -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | browser: true 3 | es2020: true 4 | extends: 5 | - standard 6 | - prettier 7 | - "plugin:@typescript-eslint/recommended" 8 | parser: "@typescript-eslint/parser" 9 | parserOptions: 10 | ecmaVersion: 11 11 | sourceType: module 12 | plugins: 13 | - "@typescript-eslint" 14 | - "prettier" 15 | rules: 16 | { 17 | "@typescript-eslint/no-unused-vars": "off", 18 | "no-use-before-define": "off", 19 | "@typescript-eslint/no-unused-vars-experimental": "off", 20 | "no-unused-vars": "off", 21 | "prettier/prettier": "error", 22 | "linebreak-style": ["error", "unix"], 23 | } 24 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | dist-client 3 | build 4 | node_modules/ 5 | **/src/generated/ 6 | .serverless/ 7 | .terraform/ 8 | terraform.tfstate* 9 | terraform.tfstate 10 | terraform.tfvars* 11 | 12 | client-installers/ 13 | 14 | # Build files from pkg 15 | 16 | .DS_Store 17 | 18 | backend/test/integration/registry-client.ts 19 | .idea 20 | gc.json 21 | 22 | backend/tmp-registry-server-storage 23 | backend/tmp-registry-server-storage-* 24 | 25 | *.p12 26 | *.avro 27 | 28 | lib/src/DataPMVersion.ts -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 16.14.2 -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | test/registry-client.ts 2 | .terraform 3 | dist 4 | 5 | backend/dist 6 | backend/node_modules 7 | backend/src/generated/graphql.ts 8 | backend/test/integration/registry-client.ts 9 | 10 | frontend/node_modules 11 | frontend/dist 12 | frontend/src/generated/graphql.ts 13 | 14 | docs/website/build 15 | docs/website/node_modules 16 | 17 | client/dist 18 | client/pkg 19 | client/node_modules 20 | client/*.datapm.json 21 | client/*.LICENSE.md 22 | client/*.README.md 23 | client/src/generated/graphql.ts 24 | client/test/integration/registry-client.ts 25 | client/test/integration/test-standard-out-sink.ts -------------------------------------------------------------------------------- /.prettierrc.yaml: -------------------------------------------------------------------------------- 1 | # Reference: https://prettier.io/docs/en/options.html 2 | 3 | tabWidth: 4 4 | useTabs: false 5 | printWidth: 120 6 | 7 | trailingComma: none 8 | bracketSpacing: true 9 | jsxBracketSameLine: true 10 | 11 | semi: true 12 | arrowParens: always 13 | singleQuote: false 14 | -------------------------------------------------------------------------------- /.snyk: -------------------------------------------------------------------------------- 1 | # Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. 2 | version: v1.13.5 3 | ignore: {} 4 | patch: {} 5 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "esbenp.prettier-vscode", 4 | "ms-azuretools.vscode-docker", 5 | "dbaeumer.vscode-eslint", 6 | "angular.ng-template", 7 | "streetsidesoftware.code-spell-checker" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": false, 3 | "editor.codeActionsOnSave": { 4 | "source.fixAll.eslint": true 5 | }, 6 | "eslint.format.enable": true, 7 | "eslint.lintTask.enable": true, 8 | "eslint.alwaysShowStatus": true, 9 | "eslint.workingDirectories": ["./client"], 10 | "prettier.configPath": ".prettierrc.yaml" 11 | } 12 | -------------------------------------------------------------------------------- /.vscode/terminals.json: -------------------------------------------------------------------------------- 1 | { 2 | "autorun": true, 3 | "terminals": [ 4 | { 5 | "name": "docker", 6 | "cwd": "docker" 7 | }, 8 | { 9 | "name": "backend", 10 | "cwd": "backend" 11 | }, 12 | { 13 | "name": "frontend", 14 | "cwd": "frontend" 15 | }, 16 | { 17 | "name": "lib", 18 | "cwd": "lib" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | See [https://datapm.io/docs/license](https://datapm.io/docs/license) 4 | -------------------------------------------------------------------------------- /backend/.bablerc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOpts": { 3 | "plugins": ["typescript", "flow"] 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /backend/.gitignore: -------------------------------------------------------------------------------- 1 | *.avro 2 | *.schema.json -------------------------------------------------------------------------------- /backend/.prettierrc.yaml: -------------------------------------------------------------------------------- 1 | # Reference: https://prettier.io/docs/en/options.html 2 | 3 | tabWidth: 4 4 | useTabs: false 5 | printWidth: 120 6 | 7 | trailingComma: none 8 | bracketSpacing: true 9 | jsxBracketSameLine: true 10 | 11 | semi: true 12 | arrowParens: always 13 | singleQuote: false 14 | -------------------------------------------------------------------------------- /backend/.snyk: -------------------------------------------------------------------------------- 1 | # Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. 2 | version: v1.13.5 3 | ignore: {} 4 | patch: {} 5 | -------------------------------------------------------------------------------- /backend/env-local.sh: -------------------------------------------------------------------------------- 1 | # Used to override env.sh environment variables with values used 2 | # during local development. 3 | export SMTP_SERVER=localhost 4 | export SMTP_PORT=1025 5 | -------------------------------------------------------------------------------- /backend/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: "ts-jest", 3 | testEnvironment: "node", 4 | testRegex: "(/tests/.*|\\.(test|spec))\\.(ts|tsx|js)$" 5 | }; 6 | -------------------------------------------------------------------------------- /backend/meta/content: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "$id": "https://json-schema.org/draft/2019-09/meta/content", 4 | "$vocabulary": { 5 | "https://json-schema.org/draft/2019-09/vocab/content": true 6 | }, 7 | "$recursiveAnchor": true, 8 | 9 | "title": "Content vocabulary meta-schema", 10 | 11 | "type": ["object", "boolean"], 12 | "properties": { 13 | "contentMediaType": { "type": "string" }, 14 | "contentEncoding": { "type": "string" }, 15 | "contentSchema": { "$recursiveRef": "#" } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /backend/meta/format: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "$id": "https://json-schema.org/draft/2019-09/meta/format", 4 | "$vocabulary": { 5 | "https://json-schema.org/draft/2019-09/vocab/format": true 6 | }, 7 | "$recursiveAnchor": true, 8 | 9 | "title": "Format vocabulary meta-schema", 10 | "type": ["object", "boolean"], 11 | "properties": { 12 | "format": { "type": "string" } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /backend/src/directive/ValidationConstraint.ts: -------------------------------------------------------------------------------- 1 | export interface ValidationConstraint { 2 | getName(): string; 3 | validate(value: string): void; 4 | getCompatibleScalarKinds(): string[]; 5 | } 6 | -------------------------------------------------------------------------------- /backend/src/entity/EntityBaseModel.ts: -------------------------------------------------------------------------------- 1 | import { Column, CreateDateColumn, UpdateDateColumn } from "typeorm"; 2 | 3 | export abstract class EntityBaseModel { 4 | @CreateDateColumn({ name: "created_at", default: () => "CURRENT_TIMESTAMP" }) 5 | createdAt: Date; 6 | 7 | @UpdateDateColumn({ nullable: true, name: "updated_at", default: () => "CURRENT_TIMESTAMP" }) 8 | updatedAt: Date; 9 | } 10 | -------------------------------------------------------------------------------- /backend/src/entity/PackageIssueStatus.ts: -------------------------------------------------------------------------------- 1 | export enum PackageIssueStatus { 2 | OPEN = "OPEN", 3 | CLOSED = "CLOSED" 4 | } 5 | -------------------------------------------------------------------------------- /backend/src/entity/Permissions.ts: -------------------------------------------------------------------------------- 1 | export enum Permissions { 2 | Manage = "MANAGE", 3 | Create = "CREATE", 4 | View = "VIEW", 5 | Edit = "EDIT", 6 | Delete = "DELETE", 7 | None = "NONE" 8 | } 9 | -------------------------------------------------------------------------------- /backend/src/entity/PlatformSettingsEntity.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity, PrimaryGeneratedColumn, Unique } from "typeorm"; 2 | import { EntityBaseModel } from "./EntityBaseModel"; 3 | 4 | @Entity({ 5 | name: "platform_settings" 6 | }) 7 | @Unique(["id"]) 8 | @Unique(["key"]) 9 | export class PlatformSettingsEntity extends EntityBaseModel { 10 | @PrimaryGeneratedColumn() 11 | public id: number; 12 | 13 | @Column() 14 | public key: string; 15 | 16 | @Column({ name: "serialized_settings" }) 17 | public serializedSettings: string; 18 | 19 | @Column({ name: "is_public" }) 20 | public isPublic: boolean; 21 | } 22 | -------------------------------------------------------------------------------- /backend/src/entity/PlatformStateEntity.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity, PrimaryGeneratedColumn, Unique } from "typeorm"; 2 | import { EntityBaseModel } from "./EntityBaseModel"; 3 | 4 | @Entity({ 5 | name: "platform_state" 6 | }) 7 | @Unique(["id"]) 8 | @Unique(["key"]) 9 | export class PlatformStateEntity extends EntityBaseModel { 10 | @PrimaryGeneratedColumn() 11 | public id: number; 12 | 13 | @Column() 14 | public key: string; 15 | 16 | @Column({ name: "serialized_state" }) 17 | public serializedState: string; 18 | } 19 | -------------------------------------------------------------------------------- /backend/src/migration/1598918058446-UserPassword.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const SQL = ` 4 | ALTER TABLE "public"."user" ADD COLUMN password_hash VARCHAR(255) DEFAULT 'zx7FmJPuyN5SL' NOT NULL ; 5 | ALTER TABLE "public"."user" ADD COLUMN password_salt VARCHAR(255) DEFAULT 'dfasdf2rffsadfa' NOT NULL ; 6 | `; 7 | 8 | export class UserPassword1598918058446 implements MigrationInterface { 9 | public async up(queryRunner: QueryRunner): Promise { 10 | queryRunner.manager.query(SQL); 11 | } 12 | 13 | public async down(queryRunner: QueryRunner): Promise { 14 | // no-op 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /backend/src/migration/1599138803334-OptionalFields.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const SQL = ` 4 | ALTER TABLE "public"."package" ALTER COLUMN description DROP NOT NULL; 5 | ALTER TABLE "public"."catalog" ALTER COLUMN description DROP NOT NULL; 6 | `; 7 | 8 | export class OptionalFields1599138803334 implements MigrationInterface { 9 | public async up(queryRunner: QueryRunner): Promise { 10 | queryRunner.query(SQL); 11 | } 12 | 13 | public async down(queryRunner: QueryRunner): Promise { 14 | // no-op 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /backend/src/migration/1599184202352-APIKeyChanges2.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const SQL = ` 4 | ALTER TABLE "apiKey" ALTER COLUMN id TYPE text; 5 | `; 6 | export class APIKeyChanges21599184202352 implements MigrationInterface { 7 | public async up(queryRunner: QueryRunner): Promise { 8 | queryRunner.query(SQL); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | // no-op 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /backend/src/migration/1599184609581-APIKeyChanges3.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const SQL = ` 4 | ALTER TABLE "apiKey" ADD CONSTRAINT uniqueUserLabels UNIQUE(user_id,label) 5 | `; 6 | export class APIKeyChanges31599184609581 implements MigrationInterface { 7 | public async up(queryRunner: QueryRunner): Promise { 8 | queryRunner.query(SQL); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | // no-op 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /backend/src/migration/1599791266154-FullTextSearch-1.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const SQL = ` 4 | 5 | ALTER TABLE package ADD COLUMN displayName_tokens TSVECTOR; 6 | ALTER TABLE package ADD COLUMN description_tokens TSVECTOR; 7 | 8 | `; 9 | export class FullTextSearch11599791266154 implements MigrationInterface { 10 | public async up(queryRunner: QueryRunner): Promise { 11 | queryRunner.query(SQL); 12 | } 13 | 14 | public async down(queryRunner: QueryRunner): Promise { 15 | // no-op 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /backend/src/migration/1599791878226-FullTextSearch-2.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const SQL = `UPDATE package SET displayName_tokens = to_tsvector(package."displayName"), description_tokens = to_tsvector(description)`; 4 | export class FullTextSearch21599791878226 implements MigrationInterface { 5 | public async up(queryRunner: QueryRunner): Promise { 6 | queryRunner.query(SQL); 7 | } 8 | 9 | public async down(queryRunner: QueryRunner): Promise { 10 | // no-op 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /backend/src/migration/1603329332326-FixPackageSlugUniqueIndex.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const sql = ` 4 | DROP INDEX idx_package_slug; 5 | CREATE UNIQUE INDEX idx_package_slug ON package ((lower(slug)),catalog_id); 6 | 7 | 8 | `; 9 | export class FixPackageSlugUniqueIndex1603329332326 implements MigrationInterface { 10 | public async up(queryRunner: QueryRunner): Promise { 11 | queryRunner.query(sql); 12 | } 13 | 14 | public async down(queryRunner: QueryRunner): Promise { 15 | // no-op 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /backend/src/migration/1604759899328-DropImageTable.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const sql = ` 4 | 5 | DROP TABLE image; 6 | 7 | `; 8 | export class DropImageTable1604759899328 implements MigrationInterface { 9 | public async up(queryRunner: QueryRunner): Promise { 10 | queryRunner.query(sql); 11 | } 12 | 13 | public async down(queryRunner: QueryRunner): Promise { 14 | // no-op 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /backend/src/migration/1605722637632-AddForgotPasswordToken.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const sql = ` 4 | ALTER TABLE "public"."user" ADD COLUMN "password_recovery_token" VARCHAR(255) DEFAULT NULL; 5 | `; 6 | 7 | export class addForgotPasswordToken1605722637632 implements MigrationInterface { 8 | public async up(queryRunner: QueryRunner): Promise { 9 | queryRunner.query(sql); 10 | } 11 | 12 | public async down(queryRunner: QueryRunner): Promise { 13 | // no-op 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /backend/src/migration/1605892679689-AddForgotPasswordTokenDate.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const sql = ` 4 | ALTER TABLE "public"."user" ADD COLUMN "password_recovery_token_date" TIMESTAMP WITH TIME ZONE; 5 | `; 6 | 7 | export class AddForgotPasswordTokenDate1605892679689 implements MigrationInterface { 8 | public async up(queryRunner: QueryRunner): Promise { 9 | queryRunner.query(sql); 10 | } 11 | 12 | public async down(queryRunner: QueryRunner): Promise { 13 | // no-op 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /backend/src/migration/1609348606379-ActivityLogAddIndex.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const sql = ` 4 | CREATE INDEX activity_log_user_id_event_type_idx ON "public"."activity_log" (user_id, event_type); 5 | `; 6 | 7 | export class ActivityLogAddIndex1609348606379 implements MigrationInterface { 8 | public async up(queryRunner: QueryRunner): Promise { 9 | queryRunner.query(sql); 10 | } 11 | 12 | public async down(queryRunner: QueryRunner): Promise { 13 | // no-op 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /backend/src/migration/1609553026656-CatalogPackagePermissions.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const sql = ` 4 | 5 | ALTER TABLE user_catalog ADD COLUMN package_permission user_package_permission_permission_enum[] NOT NULL DEFAULT '{}'; 6 | `; 7 | 8 | export class CatalogPackagePermissions1609553026656 implements MigrationInterface { 9 | public async up(queryRunner: QueryRunner): Promise { 10 | queryRunner.query(sql); 11 | } 12 | 13 | public async down(queryRunner: QueryRunner): Promise { 14 | // no-op 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /backend/src/migration/1609902949161-CatalogCreator.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const sql = ` 4 | ALTER TABLE catalog ADD COLUMN IF NOT EXISTS creator_id BIGINT; 5 | `; 6 | export class CatalogCreator1609902949161 implements MigrationInterface { 7 | public async up(queryRunner: QueryRunner): Promise { 8 | queryRunner.query(sql); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | // no-op 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /backend/src/migration/1610566212911-DeleteAllPackages.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | export class DeleteAllPackages1610566212911 implements MigrationInterface { 4 | public async up(queryRunner: QueryRunner): Promise { 5 | return queryRunner.query("Delete from package"); 6 | } 7 | 8 | public async down(queryRunner: QueryRunner): Promise { 9 | // no-op 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /backend/src/migration/1611026765149-InviteUser.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const sql = ` 4 | ALTER TABLE "public"."user" ALTER COLUMN "username" drop not NULL; 5 | ALTER TABLE "public"."user" ALTER COLUMN "password_hash" drop not NULL; 6 | ALTER TABLE "public"."user" ALTER COLUMN "password_salt" drop not NULL; 7 | `; 8 | export class InviteUser1611026765149 implements MigrationInterface { 9 | public async up(queryRunner: QueryRunner): Promise { 10 | queryRunner.query(sql); 11 | } 12 | 13 | public async down(queryRunner: QueryRunner): Promise { 14 | // no-op 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /backend/src/migration/1612111338969-AddTargetUserColumnForActivityLogTable.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | export class AddTargetUserColumnForActivityLogTable1612111338969 implements MigrationInterface { 4 | public async up(queryRunner: QueryRunner): Promise { 5 | return queryRunner.query("ALTER TABLE public.activity_log ADD COLUMN target_user_id INTEGER"); 6 | } 7 | 8 | public async down(queryRunner: QueryRunner): Promise { 9 | // no-op 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /backend/src/migration/1615996821186-AddUIDarkModeColumnToUserTable.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | export class AddUIDarkModeColumnToUserTable1615996821186 implements MigrationInterface { 4 | public async up(queryRunner: QueryRunner): Promise { 5 | return queryRunner.query(` 6 | ALTER TABLE "user" ADD COLUMN IF NOT EXISTS "ui_dark_mode_enabled" BOOLEAN DEFAULT FALSE; 7 | `); 8 | } 9 | 10 | public async down(queryRunner: QueryRunner): Promise { 11 | // no-op 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /backend/src/migration/1618415843311-AddVersionTrivialChangeType.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | const sql = ` 3 | ALTER TYPE activity_log_change_type_enum ADD VALUE 'VERSION_TRIVIAL_CHANGE'; 4 | ALTER TYPE activity_log_event_type_enum ADD VALUE 'VERSION_UPDATED'; 5 | `; 6 | export class AddVersionTrivialChangeType1618415843311 implements MigrationInterface { 7 | public async up(queryRunner: QueryRunner): Promise { 8 | await queryRunner.query(sql); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | // no-op 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /backend/src/migration/1620666572765-AddUnclaimedCatalogColumn.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | export class AddUnclaimedCatalogColumn1620666572765 implements MigrationInterface { 4 | public async up(queryRunner: QueryRunner): Promise { 5 | const sql = "ALTER TABLE catalog ADD COLUMN IF NOT EXISTS unclaimed BOOLEAN DEFAULT FALSE"; 6 | return queryRunner.query(sql); 7 | } 8 | 9 | public async down(queryRunner: QueryRunner): Promise { 10 | // no-op 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /backend/src/migration/1620769501264-MakeActivityLogTableChangeTypeColumnAVarChar.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | export class MakeActivityLogTableChangeTypeColumnAVarChar1620769501264 implements MigrationInterface { 4 | public async up(queryRunner: QueryRunner): Promise { 5 | const query = 'ALTER TABLE public."activity_log" ALTER COLUMN change_type TYPE VARCHAR(255)'; 6 | return queryRunner.query(query); 7 | } 8 | 9 | public async down(queryRunner: QueryRunner): Promise { 10 | // no-op 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /backend/src/migration/1624567282854-PackageFollowCorrection.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const sql = ` 4 | UPDATE follow SET event_types = '{VERSION_CREATED,PACKAGE_EDIT}' WHERE target_package_id IS NOT NULL AND target_package_issue_id IS NULL 5 | `; 6 | export class PackageFollowCorrection1624567282854 implements MigrationInterface { 7 | public async up(queryRunner: QueryRunner): Promise { 8 | queryRunner.query(sql); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | // no-op 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /backend/src/migration/1625845662069-AddUnclaimedLogTypesEnumToDbObject.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | export class AddUnclaimedLogTypesEnumToDbObject1625845662069 implements MigrationInterface { 4 | public async up(queryRunner: QueryRunner): Promise { 5 | await queryRunner.connection.query("ALTER TYPE activity_log_change_type_enum ADD VALUE 'UNCLAIMED_ENABLED'"); 6 | await queryRunner.connection.query("ALTER TYPE activity_log_change_type_enum ADD VALUE 'UNCLAIMED_DISABLED'"); 7 | } 8 | 9 | public async down(queryRunner: QueryRunner): Promise { 10 | // no-op 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /backend/src/migration/1648151610519-PackageLastUpdateJob.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const sql = ` 4 | ALTER TABLE "package" ADD COLUMN "last_update_job_date" timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL; 5 | `; 6 | export class PackageLastUpdateJob1648151610519 implements MigrationInterface { 7 | public async up(queryRunner: QueryRunner): Promise { 8 | await queryRunner.query(sql); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | // no-op 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /backend/src/migration/1649190799043-UpdateMethod.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const sql = ` 4 | alter table "public"."version" add column update_methods jsonb; 5 | `; 6 | export class UpdateMethod1649190799043 implements MigrationInterface { 7 | public async up(queryRunner: QueryRunner): Promise { 8 | await queryRunner.query(sql); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | // no-op 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /backend/src/migration/1660663641407-ActivityLogPermissions.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const sql = ` 4 | 5 | ALTER TABLE activity_log ADD COLUMN permissions text[]; 6 | 7 | `; 8 | 9 | export class ActivityLogPermissions1660663641407 implements MigrationInterface { 10 | public async up(queryRunner: QueryRunner): Promise { 11 | await queryRunner.query(sql); 12 | } 13 | 14 | public async down(queryRunner: QueryRunner): Promise { 15 | // no-op 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /backend/src/migration/1662572838241-GroupAdmin.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const sql = ` 4 | ALTER TABLE "group" ADD COLUMN "is_admin" boolean NOT NULL DEFAULT false; 5 | `; 6 | 7 | export class GroupAdmin1662572838241 implements MigrationInterface { 8 | public async up(queryRunner: QueryRunner): Promise { 9 | await queryRunner.query(sql); 10 | } 11 | 12 | public async down(queryRunner: QueryRunner): Promise { 13 | // no-op 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /backend/src/migration/1663619631799-CreatorIdFixes.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const sql = ` 4 | ALTER TABLE public.collection ALTER COLUMN creator_id TYPE int4; 5 | ALTER TABLE public.catalog ALTER COLUMN creator_id TYPE int4; 6 | ALTER TABLE public.package ALTER COLUMN creator_id TYPE int4; 7 | `; 8 | 9 | export class CreatorIdFixes1663619631799 implements MigrationInterface { 10 | public async up(queryRunner: QueryRunner): Promise { 11 | await queryRunner.query(sql); 12 | } 13 | 14 | public async down(queryRunner: QueryRunner): Promise { 15 | // no-op 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /backend/src/migration/1668544666051-FetchJobActivities.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | const sql = ` 4 | ALTER TYPE activity_log_event_type_enum ADD VALUE 'FETCH_JOB_STARTED'; 5 | ALTER TYPE activity_log_event_type_enum ADD VALUE 'FETCH_JOB_ENDED'; 6 | `; 7 | 8 | export class FetchJobActivities1668544666051 implements MigrationInterface { 9 | public async up(queryRunner: QueryRunner): Promise { 10 | await queryRunner.query(sql); 11 | } 12 | 13 | public async down(queryRunner: QueryRunner): Promise { 14 | // no-op 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /backend/src/repository/OrderBy.ts: -------------------------------------------------------------------------------- 1 | export enum OrderBy { 2 | CREATED_AT = "created_at", 3 | UPDATED_AT = "updated_at" 4 | } 5 | -------------------------------------------------------------------------------- /backend/src/repository/PlatformStateRepository.ts: -------------------------------------------------------------------------------- 1 | import { EntityRepository, Repository } from "typeorm"; 2 | import { PlatformStateEntity } from "../entity/PlatformStateEntity"; 3 | 4 | @EntityRepository(PlatformStateEntity) 5 | export class PlatformStateRepository extends Repository { 6 | public async findStateByKey(key: string): Promise { 7 | return await this.createQueryBuilder().where("key = :key").setParameter("key", key).getOne(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /backend/src/resolvers/FirstUserStatusHolder.ts: -------------------------------------------------------------------------------- 1 | export class FirstUserStatusHolder { 2 | public static IS_FIRST_USER_CREATED = false; 3 | } 4 | -------------------------------------------------------------------------------- /backend/src/storage/images/catalog-avatar-image-processor.ts: -------------------------------------------------------------------------------- 1 | import { ImageProcessor } from "./image-processor"; 2 | import { ResizeOptions } from "sharp"; 3 | 4 | export class CatalogAvatarImageProcessor extends ImageProcessor { 5 | getResizeOptions(): ResizeOptions { 6 | return { 7 | width: 500, 8 | height: 500 9 | }; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /backend/src/storage/images/catalog-cover-image-processor.ts: -------------------------------------------------------------------------------- 1 | import { ImageProcessor } from "./image-processor"; 2 | import { ResizeOptions } from "sharp"; 3 | 4 | export class CatalogCoverImageProcessor extends ImageProcessor { 5 | getResizeOptions(): ResizeOptions { 6 | return { 7 | width: 1000, 8 | height: 500 9 | }; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /backend/src/storage/images/collection-cover-image-processor.ts: -------------------------------------------------------------------------------- 1 | import { ImageProcessor } from "./image-processor"; 2 | import { ResizeOptions } from "sharp"; 3 | 4 | export class CollectionCoverImageProcessor extends ImageProcessor { 5 | getResizeOptions(): ResizeOptions { 6 | return { 7 | width: 1000, 8 | height: 500 9 | }; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /backend/src/storage/images/package-cover-image-processor.ts: -------------------------------------------------------------------------------- 1 | import { ImageProcessor } from "./image-processor"; 2 | import { ResizeOptions } from "sharp"; 3 | 4 | export class PackageCoverImageProcessor extends ImageProcessor { 5 | getResizeOptions(): ResizeOptions { 6 | return { 7 | width: 1000, 8 | height: 500 9 | }; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /backend/src/storage/images/user-avatar-image-processor.ts: -------------------------------------------------------------------------------- 1 | import { ImageProcessor } from "./image-processor"; 2 | import { ResizeOptions } from "sharp"; 3 | 4 | export class UserAvatarImageProcessor extends ImageProcessor { 5 | getResizeOptions(): ResizeOptions { 6 | return { 7 | width: 500, 8 | height: 500 9 | }; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /backend/src/storage/images/user-cover-image-processor.ts: -------------------------------------------------------------------------------- 1 | import { ImageProcessor } from "./image-processor"; 2 | import { ResizeOptions } from "sharp"; 3 | 4 | export class UserCoverImageProcessor extends ImageProcessor { 5 | getResizeOptions(): ResizeOptions { 6 | return { 7 | width: 1000, 8 | height: 500 9 | }; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /backend/src/types/base62/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "base62/lib/ascii" { 2 | export function encode(value: string): string; 3 | export function decode(value: string): string; 4 | } 5 | -------------------------------------------------------------------------------- /backend/src/types/buffer-peek-stream/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "buffer-peek-stream" { 2 | import { Readable } from "stream"; 3 | 4 | export function promise(stream: Readable, size: number): Promise<[Buffer, Readable]>; 5 | } 6 | -------------------------------------------------------------------------------- /backend/src/types/minizlib/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "minizlib" { 2 | import { Transform, TransformOptions } from "stream"; 3 | 4 | export class Gzip extends Transform { 5 | constructor(options?: TransformOptions); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /backend/src/util/EncryptionUtil.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | import { randomUUID } from "crypto"; 3 | import { describe, it } from "mocha"; 4 | import { decryptValue, encryptValue } from "./EncryptionUtil"; 5 | 6 | describe("Encryption Utils", () => { 7 | it("Should encrypt/decrypt values", () => { 8 | const value = randomUUID(); 9 | 10 | process.env.NODEJS_ENCRYPTION_KEY = randomUUID(); 11 | 12 | const encryptedValue = encryptValue(value); 13 | 14 | const decryptedValue = decryptValue(encryptedValue); 15 | 16 | expect(value).equal(decryptedValue); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /backend/src/util/GraphQLFieldsType.ts: -------------------------------------------------------------------------------- 1 | export type GraphQLFields = { 2 | [key: string]: GraphQLFields; 3 | }; 4 | -------------------------------------------------------------------------------- /backend/src/util/PasswordUtil.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | import { hashPassword } from "./PasswordUtil"; 3 | 4 | describe("Passwordhasing", () => { 5 | it("THIS SHOULD NEVER CHANGE", () => { 6 | expect(hashPassword("abc12345", "mysalting")).equal("EPC2FzkvT3wmyml/ixDgb9G36NufR0IanKWysDWAsaw="); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /backend/src/util/PasswordUtil.ts: -------------------------------------------------------------------------------- 1 | import { createHmac } from "crypto"; 2 | 3 | export function hashPassword(password: string, salt: string): string { 4 | return createHmac("sha256", salt).update(password).digest("base64"); 5 | } 6 | -------------------------------------------------------------------------------- /backend/src/util/PermissionsUtil.ts: -------------------------------------------------------------------------------- 1 | import { Permission } from "../generated/graphql"; 2 | 3 | export function allPermissions(): Permission[] { 4 | return [Permission.EDIT, Permission.MANAGE, Permission.VIEW]; 5 | } 6 | -------------------------------------------------------------------------------- /backend/src/util/getEnvVariable.ts: -------------------------------------------------------------------------------- 1 | export function getEnvVariable(name: string, defaultValue: string | undefined = undefined): string { 2 | let environmentVariable = process.env[name]; 3 | if (environmentVariable == null && defaultValue !== undefined) { 4 | environmentVariable = defaultValue; 5 | } else if (environmentVariable === undefined) { 6 | throw new Error(`The environment variable '${name}' must be set`); 7 | } 8 | return environmentVariable; 9 | } 10 | -------------------------------------------------------------------------------- /backend/startServer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo "Starting Server" 3 | node index.js -------------------------------------------------------------------------------- /backend/static/email-templates/api-key-created.txt: -------------------------------------------------------------------------------- 1 | A new API key has been created for your the user {{username}} on {{registry_name}} at {{registry_url}}. 2 | 3 | If you did not create this API key, please do the following quickly. 4 | 5 | 1. Login to {{registry_url}} 6 | 2. Delete the API Key named {{api_key_label}} 7 | 3. Change your account password 8 | 4. Reply to this email to report suspicious behavior 9 | 10 | -------------------------------------------------------------------------------- /backend/static/email-templates/forgot-password.txt: -------------------------------------------------------------------------------- 1 | You or someone else requested this password reset email for your username {{username}} on {{registry_name}} at {{registry_url}}. If you did not request this email, please delete it from your inbox. 2 | 3 | Click, or copy-and-paste into your browser, the link below to create a new password. 4 | 5 | {{registry_url}}/password-recovery?token={{token}} -------------------------------------------------------------------------------- /backend/static/email-templates/share-notification.txt: -------------------------------------------------------------------------------- 1 | {{ inviter_name }} has shared {{ data_name }} with you. 2 | 3 | {{ message }} 4 | 5 | Click or copy and paste the url below to access this data. 6 | 7 | {{ url }} 8 | -------------------------------------------------------------------------------- /backend/static/email-templates/user-invite.txt: -------------------------------------------------------------------------------- 1 | {{inviter_name}} has invited you to collaborate on {{data_name}} data at {{registry_name}}. 2 | 3 | {{message}} 4 | Use the link below to get started. 5 | 6 | {{registry_url}}/accept-invite?token={{token}} 7 | 8 | -------------------------------------------------------------------------------- /backend/static/email-templates/user-suspended.txt: -------------------------------------------------------------------------------- 1 | Hello, {{username}}, 2 | 3 | Your account in {{registry_url}} at {{registry_name}} has been suspended with the following message: 4 | {{message}} -------------------------------------------------------------------------------- /backend/static/email-templates/validate-email-address.txt: -------------------------------------------------------------------------------- 1 | Thanks for requesting access to {{registry_name}} at {{registry_url}} 2 | 3 | Click (or copy-and-paste in your browser) the link below to validate your email address. 4 | 5 | {{registry_url}}/validate-email?token={{token}} 6 | 7 | If you did not request this email, you can safely ignore it. You not receive any further communications. -------------------------------------------------------------------------------- /backend/static/index.html: -------------------------------------------------------------------------------- 1 | datapm registry server. The frontend dist folder contents were not used to overwrite this temporary index.html file. 2 | -------------------------------------------------------------------------------- /backend/static/robots-production.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | Sitemap: ${REGISTRY_URL}/sitemap.xml -------------------------------------------------------------------------------- /backend/static/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: / -------------------------------------------------------------------------------- /backend/test/data-files/data.avro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/backend/test/data-files/data.avro -------------------------------------------------------------------------------- /backend/test/data-files/postgres-test-data.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE test ( 2 | id serial PRIMARY KEY, 3 | name varchar(255) NOT NULL, 4 | age integer NOT NULL 5 | ); 6 | 7 | INSERT INTO test (name, age) VALUES ('John', 42); 8 | INSERT INTO test (name, age) VALUES ('Jane', 43); 9 | INSERT INTO test (name, age) VALUES ('Joe', 44); 10 | INSERT INTO test (name, age) VALUES ('Jack', 45); 11 | 12 | -------------------------------------------------------------------------------- /backend/test/data-files/postgres-test-update.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE test RENAME COLUMN name TO name_new; -------------------------------------------------------------------------------- /backend/test/data-files/simple/simple.LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | License not defined. Contact author. -------------------------------------------------------------------------------- /backend/test/data-files/simple/simple.README.md: -------------------------------------------------------------------------------- 1 | # Simple 2 | 3 | Simple data for testing -------------------------------------------------------------------------------- /backend/test/data-files/simple/simple.csv: -------------------------------------------------------------------------------- 1 | string,number,boolean,date,datetime,stringNulls 2 | hey,1,true,11/12/1980,"Tue, 14 Sep 2021 19:23:11 GMT", 3 | yo,2.2,false,1/1/2001,"Tue, 14 Sep 2021 19:23:11 GMT",something here -------------------------------------------------------------------------------- /backend/test/data-files/start-small-donations.avro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/backend/test/data-files/start-small-donations.avro -------------------------------------------------------------------------------- /backend/test/integration/admin-holder.ts: -------------------------------------------------------------------------------- 1 | import { ApolloClient, NormalizedCacheObject } from "@apollo/client/core"; 2 | 3 | export class AdminHolder { 4 | public static adminClient: ApolloClient; 5 | public static adminUsername: string; 6 | } 7 | -------------------------------------------------------------------------------- /backend/test/integration/constants.ts: -------------------------------------------------------------------------------- 1 | import { RandomUuid } from "testcontainers/dist/uuid"; 2 | 3 | export const TEMP_STORAGE_PATH: string = "tmp-registry-server-storage-" + new RandomUuid().nextUuid(); 4 | -------------------------------------------------------------------------------- /backend/test/other-files/ba.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/backend/test/other-files/ba.jpg -------------------------------------------------------------------------------- /backend/test/packageFiles/congressional-legislators.LICENSE.md: -------------------------------------------------------------------------------- 1 | # Test License 2 | 3 | This is not a real license. Just a test. 4 | -------------------------------------------------------------------------------- /backend/test/packageFiles/congressional-legislators.README.md: -------------------------------------------------------------------------------- 1 | # Test README 2 | 3 | This is where a readme might go. 4 | -------------------------------------------------------------------------------- /backend/test/packageFiles/test-update-package.LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | License not defined. Contact author. -------------------------------------------------------------------------------- /backend/test/packageFiles/test-update-package.README.md: -------------------------------------------------------------------------------- 1 | # Test Update Package 2 | 3 | for testing UpdateJob via websockets -------------------------------------------------------------------------------- /backend/test/packageFiles/v0.1.0/congressional-legislators.LICENSE.md: -------------------------------------------------------------------------------- 1 | # Test License 2 | 3 | This is not a real license. Just a test. 4 | -------------------------------------------------------------------------------- /backend/test/packageFiles/v0.1.0/congressional-legislators.README.md: -------------------------------------------------------------------------------- 1 | # Test README 2 | 3 | This is where a readme might go. 4 | -------------------------------------------------------------------------------- /backend/test/sources/update-test-changes.csv: -------------------------------------------------------------------------------- 1 | column1,column2,column3 2 | a,1,more 3 | b,2,some 4 | c,3,less -------------------------------------------------------------------------------- /backend/test/sources/update-test-original.csv: -------------------------------------------------------------------------------- 1 | column1,column2 2 | a,1 3 | b,2 -------------------------------------------------------------------------------- /backend/tsconfig.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "outDir": "build/module", 6 | "module": "esnext" 7 | }, 8 | "exclude": ["node_modules/**"] 9 | } 10 | -------------------------------------------------------------------------------- /backend/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": ["tslint:recommended"], 4 | "jsRules": {}, 5 | "rules": { 6 | "no-console": false 7 | }, 8 | "rulesDirectory": [] 9 | } 10 | -------------------------------------------------------------------------------- /client-lib/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | pkg 5 | pkg* 6 | src/generated 7 | test/integration/registry-client.ts 8 | !*.datapm.json 9 | *.datapm.json 10 | *.datapm.state.json 11 | !*.LICENSE.md 12 | *.LICENSE.md 13 | !*.README.md 14 | *.README.md 15 | datapm-state.json 16 | *state.json 17 | countries* 18 | *.csv 19 | test/credentials 20 | temp 21 | signing-certificiate.* 22 | temp 23 | *.msix 24 | *.p12 25 | *.pfx 26 | windows-installers 27 | *.crt 28 | *.cert 29 | *.pkg 30 | *.deb 31 | pkg-* 32 | 33 | installers/macos/macOS-x64/application 34 | installers/debian/build 35 | installers/redhat/build 36 | installers/windows/dist 37 | -------------------------------------------------------------------------------- /client-lib/src/connector/database/big-query/BigQuerySinkDescription.ts: -------------------------------------------------------------------------------- 1 | import { Sink, SinkDescription } from "../../Sink"; 2 | import { DISPLAY_NAME, TYPE } from "./BigQueryConnectorDescription"; 3 | 4 | export class BigQuerySinkDescription implements SinkDescription { 5 | getType(): string { 6 | return TYPE; 7 | } 8 | 9 | getDisplayName(): string { 10 | return DISPLAY_NAME; 11 | } 12 | 13 | async loadSinkFromModule(): Promise { 14 | const module = await import("./BigQuerySink"); 15 | return new module.BigQuerySink(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/connector/database/mongo/MongoSinkDescription.ts: -------------------------------------------------------------------------------- 1 | import { Sink, SinkDescription } from "../../Sink"; 2 | 3 | import { TYPE, DISPLAY_NAME } from "./MongoConnectorDescription"; 4 | 5 | export class MongoSinkDescription implements SinkDescription { 6 | getType(): string { 7 | return TYPE; 8 | } 9 | 10 | getDisplayName(): string { 11 | return DISPLAY_NAME; 12 | } 13 | 14 | async loadSinkFromModule(): Promise { 15 | const module = await import("./MongoSink"); 16 | return new module.MongoSinkModule(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /client-lib/src/connector/database/mysql/MySqlSinkDescription.ts: -------------------------------------------------------------------------------- 1 | import { Sink, SinkDescription } from "../../Sink"; 2 | import { TYPE, DISPLAY_NAME } from "./MySqlConnectorDescription"; 3 | 4 | export class MySqlSinkDescription implements SinkDescription { 5 | getType(): string { 6 | return TYPE; 7 | } 8 | 9 | getDisplayName(): string { 10 | return DISPLAY_NAME; 11 | } 12 | 13 | async loadSinkFromModule(): Promise { 14 | const module = await import("./MySqlSink"); 15 | return new module.MySqlSink(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/connector/database/postgres/PostgresSinkDescription.ts: -------------------------------------------------------------------------------- 1 | import { DISPLAY_NAME, TYPE } from "./PostgresConnectorDescription"; 2 | import { Sink, SinkDescription } from "../../Sink"; 3 | 4 | export class PostgresSinkDescription implements SinkDescription { 5 | getType(): string { 6 | return TYPE; 7 | } 8 | 9 | getDisplayName(): string { 10 | return DISPLAY_NAME; 11 | } 12 | 13 | async loadSinkFromModule(): Promise { 14 | const module = await import("./PostgresSink"); 15 | return new module.PostgresSink(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/connector/database/redshift/RedshiftSinkDescription.ts: -------------------------------------------------------------------------------- 1 | import { Sink, SinkDescription } from "../../Sink"; 2 | import { TYPE, DISPLAY_NAME } from "./RedshiftConnectorDescription"; 3 | export class RedshiftSinkDescription implements SinkDescription { 4 | getType(): string { 5 | return TYPE; 6 | } 7 | 8 | getDisplayName(): string { 9 | return DISPLAY_NAME; 10 | } 11 | 12 | async loadSinkFromModule(): Promise { 13 | const module = await import("./RedshiftSink"); 14 | return new module.RedshiftSink(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /client-lib/src/connector/decodable/DecodableSinkDescription.ts: -------------------------------------------------------------------------------- 1 | import { Sink, SinkDescription } from "../Sink"; 2 | import { DISPLAY_NAME, TYPE } from "./DecodableConnectorDescription"; 3 | 4 | export class DecodableSinkDescription implements SinkDescription { 5 | getType(): string { 6 | return TYPE; 7 | } 8 | 9 | getDisplayName(): string { 10 | return DISPLAY_NAME; 11 | } 12 | 13 | async loadSinkFromModule(): Promise { 14 | const source = await import("./DecodableSink"); 15 | return new source.DecodableSink(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/connector/file-based/datapm-registry/DataPMSinkDescription.ts: -------------------------------------------------------------------------------- 1 | import { Sink, SinkDescription } from "../../Sink"; 2 | import { TYPE, DISPLAY_NAME } from "./DataPMConnectorDescription"; 3 | export class DataPMSinkDescription implements SinkDescription { 4 | getType(): string { 5 | return TYPE; 6 | } 7 | 8 | getDisplayName(): string { 9 | return DISPLAY_NAME; 10 | } 11 | 12 | async loadSinkFromModule(): Promise { 13 | const module = await import("./DataPMSink"); 14 | return new module.DataPMSink(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /client-lib/src/connector/file-based/local-file/LocalFileSinkDescription.ts: -------------------------------------------------------------------------------- 1 | import { Sink, SinkDescription } from "../../Sink"; 2 | import { DISPLAY_NAME, TYPE } from "./LocalFileConnectorDescription"; 3 | 4 | export class LocalFileSinkDescription implements SinkDescription { 5 | getType(): string { 6 | return TYPE; 7 | } 8 | 9 | getDisplayName(): string { 10 | return DISPLAY_NAME; 11 | } 12 | 13 | async loadSinkFromModule(): Promise { 14 | const module = await import("./LocalFileSink"); 15 | return new module.LocalFileSink(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/connector/file-based/s3/S3SinkDescription.ts: -------------------------------------------------------------------------------- 1 | import { Sink, SinkDescription } from "../../Sink"; 2 | import { TYPE, DISPLAY_NAME } from "./S3ConnectorDescription"; 3 | export class S3SinkDescription implements SinkDescription { 4 | getType(): string { 5 | return TYPE; 6 | } 7 | 8 | getDisplayName(): string { 9 | return DISPLAY_NAME; 10 | } 11 | 12 | async loadSinkFromModule(): Promise { 13 | const module = await import("./S3Sink"); 14 | return new module.S3Sink(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /client-lib/src/connector/file-based/standard-out/StandardOutSinkDescription.ts: -------------------------------------------------------------------------------- 1 | import { Sink, SinkDescription } from "../../Sink"; 2 | import { TYPE, DISPLAY_NAME } from "./StandardOutConnectorDescription"; 3 | 4 | export class StandardOutSinkDescription implements SinkDescription { 5 | getType(): string { 6 | return TYPE; 7 | } 8 | 9 | getDisplayName(): string { 10 | return DISPLAY_NAME; 11 | } 12 | 13 | async loadSinkFromModule(): Promise { 14 | const module = await import("./StandardOutSink"); 15 | return new module.StandardOutSinkModule(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/connector/ftx/FTXSourceDescription.ts: -------------------------------------------------------------------------------- 1 | import { Source, SourceDescription } from "../Source"; 2 | import { DISPLAY_NAME, TYPE, URI, URI_US } from "./FTXConnectorDescription"; 3 | 4 | export class FTXSourceDescription implements SourceDescription { 5 | sourceType(): string { 6 | return TYPE; 7 | } 8 | 9 | getDisplayName(): string { 10 | return DISPLAY_NAME; 11 | } 12 | 13 | supportsURI(uri: string): false { 14 | return false; 15 | } 16 | 17 | async getSource(): Promise { 18 | const source = await import("./FTXSource"); 19 | return new source.FTXSource(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /client-lib/src/connector/gemini/GeminiSourceDescription.ts: -------------------------------------------------------------------------------- 1 | import { Source, SourceDescription } from "../Source"; 2 | import { DISPLAY_NAME, TYPE, URI_BASE } from "./GeminiConnectorDescription"; 3 | 4 | export class GeminiSourceDescription implements SourceDescription { 5 | sourceType(): string { 6 | return TYPE; 7 | } 8 | 9 | getDisplayName(): string { 10 | return DISPLAY_NAME; 11 | } 12 | 13 | supportsURI(uri: string): false { 14 | return false; 15 | } 16 | 17 | async getSource(): Promise { 18 | const source = await import("./GeminiSource"); 19 | return new source.GeminiSource(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /client-lib/src/connector/stream/kafka/KafkaSinkDescription.ts: -------------------------------------------------------------------------------- 1 | import { Sink, SinkDescription } from "../../Sink"; 2 | import { DISPLAY_NAME, TYPE } from "./KafkaConnectorDescription"; 3 | 4 | export class KafkaSinkDescription implements SinkDescription { 5 | getType(): string { 6 | return TYPE; 7 | } 8 | 9 | getDisplayName(): string { 10 | return DISPLAY_NAME; 11 | } 12 | 13 | async loadSinkFromModule(): Promise { 14 | const description = await import("./KafkaSink"); 15 | return new description.KafkaSink(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/connector/timeplus/TimeplusSinkDescription.ts: -------------------------------------------------------------------------------- 1 | import { Sink, SinkDescription } from "../Sink"; 2 | import { DISPLAY_NAME, TYPE } from "./TimeplusConnectorDescription"; 3 | 4 | export class TimeplusSinkDescription implements SinkDescription { 5 | getType(): string { 6 | return TYPE; 7 | } 8 | 9 | getDisplayName(): string { 10 | return DISPLAY_NAME; 11 | } 12 | 13 | async loadSinkFromModule(): Promise { 14 | const source = await import("./TimeplusSink"); 15 | return new source.TimeplusSink(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/content-detector/AgePropertyNameDetector.ts: -------------------------------------------------------------------------------- 1 | import { DPMPropertyTypes } from "datapm-lib"; 2 | import { PropertyNameDetectorBase } from "./PropertyNameDetectorBase"; 3 | 4 | export const AGE_LABEL = "age"; 5 | export class AgePropertyNameDetector extends PropertyNameDetectorBase { 6 | getApplicableTypes(): DPMPropertyTypes[] { 7 | return ["integer"]; 8 | } 9 | 10 | getPropertyNameMatches(): RegExp[] { 11 | return [/^age$/i]; 12 | } 13 | 14 | getLabel(): string { 15 | return AGE_LABEL; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/content-detector/CreditCardNumberDetector.ts: -------------------------------------------------------------------------------- 1 | import { RegexDetector } from "./RegexDetector"; 2 | 3 | export const CREDIT_CARD_NUMBER = "credit_card_number"; 4 | 5 | export class CreditCardNumberDetector extends RegexDetector { 6 | getApplicableTypes(): ("string" | "integer")[] { 7 | return ["string", "integer"]; 8 | } 9 | 10 | getRegExp(): RegExp { 11 | return /\b(?:4[0-9]{12}(?:[0-9]{3})?|[25][1-7][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})\b/; 12 | } 13 | 14 | getLabel(): string { 15 | return CREDIT_CARD_NUMBER; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/content-detector/DateOfBirthPropertyNameDetector.ts: -------------------------------------------------------------------------------- 1 | import { DPMPropertyTypes } from "datapm-lib"; 2 | import { PropertyNameDetectorBase } from "./PropertyNameDetectorBase"; 3 | 4 | export const DOB_LABEL = "birthdate"; 5 | export class DateOfBirthPropertyNameDetector extends PropertyNameDetectorBase { 6 | getApplicableTypes(): DPMPropertyTypes[] { 7 | return ["string", "date"]; 8 | } 9 | 10 | getPropertyNameMatches(): RegExp[] { 11 | return [/dob|date[-_\s]?Of[-_\s]?birth|birth[-_\s]?(?:date|day)/i]; 12 | } 13 | 14 | getLabel(): string { 15 | return DOB_LABEL; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/content-detector/DriversLicensePropertyNameDetector.ts: -------------------------------------------------------------------------------- 1 | import { DPMPropertyTypes } from "datapm-lib"; 2 | import { PropertyNameDetectorBase } from "./PropertyNameDetectorBase"; 3 | 4 | export const DRIVERS_LICENSE_LABEL = "drivers_license"; 5 | export class DriversLicensePropertyNameDetector extends PropertyNameDetectorBase { 6 | getApplicableTypes(): DPMPropertyTypes[] { 7 | return ["string", "integer"]; 8 | } 9 | 10 | getPropertyNameMatches(): RegExp[] { 11 | return [/drivers?[-_\s]?license|^dl$/i]; 12 | } 13 | 14 | getLabel(): string { 15 | return DRIVERS_LICENSE_LABEL; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/content-detector/EmailContentDetector.ts: -------------------------------------------------------------------------------- 1 | import { RegexDetector } from "./RegexDetector"; 2 | 3 | export const EMAIL_ADDRESS_LABEL = "email_address"; 4 | 5 | /** Applies the 'phone_number' label when any single phone number is found in any value */ 6 | export class EmailAddressDetector extends RegexDetector { 7 | getRegExp(): RegExp { 8 | return /\S+@\S+\.\S{1,10}/; 9 | } 10 | 11 | getLabel(): string { 12 | return EMAIL_ADDRESS_LABEL; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /client-lib/src/content-detector/EthnicityPropertyNameDetector.ts: -------------------------------------------------------------------------------- 1 | import { DPMPropertyTypes } from "datapm-lib"; 2 | import { PropertyNameDetectorBase } from "./PropertyNameDetectorBase"; 3 | 4 | export const ETHNICITY_LABEL = "ethnicity"; 5 | export class EthnicityPropertyNameDetector extends PropertyNameDetectorBase { 6 | getApplicableTypes(): DPMPropertyTypes[] { 7 | return ["string"]; 8 | } 9 | 10 | getPropertyNameMatches(): RegExp[] { 11 | return [/ethnicity|race/i]; 12 | } 13 | 14 | getLabel(): string { 15 | return ETHNICITY_LABEL; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/content-detector/GenderPropertyNameDetector.ts: -------------------------------------------------------------------------------- 1 | import { DPMPropertyTypes } from "datapm-lib"; 2 | import { PropertyNameDetectorBase } from "./PropertyNameDetectorBase"; 3 | 4 | export const GENDER_LABEL = "gender"; 5 | export class GenderPropertyNameDetector extends PropertyNameDetectorBase { 6 | getApplicableTypes(): DPMPropertyTypes[] { 7 | return ["string"]; 8 | } 9 | 10 | getPropertyNameMatches(): RegExp[] { 11 | return [/gender|sex/i]; 12 | } 13 | 14 | getLabel(): string { 15 | return GENDER_LABEL; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/content-detector/GeoLatitudePropertyNameDetector.ts: -------------------------------------------------------------------------------- 1 | import { DPMPropertyTypes } from "datapm-lib"; 2 | import { PropertyNameDetectorBase } from "./PropertyNameDetectorBase"; 3 | 4 | export const GEO_LATITUDE_LABEL = "geo_latitude"; 5 | 6 | export class GeoLatitudePropertyNameDetector extends PropertyNameDetectorBase { 7 | getApplicableTypes(): DPMPropertyTypes[] { 8 | return ["number"]; 9 | } 10 | 11 | getPropertyNameMatches(): RegExp[] { 12 | return [/^lat$|latitude/i]; 13 | } 14 | 15 | getLabel(): string { 16 | return GEO_LATITUDE_LABEL; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /client-lib/src/content-detector/GeoLongitudePropertyNameDetector.ts: -------------------------------------------------------------------------------- 1 | import { DPMPropertyTypes } from "datapm-lib"; 2 | import { PropertyNameDetectorBase } from "./PropertyNameDetectorBase"; 3 | 4 | export const GEO_LONGITUDE_LABEL = "geo_longitude"; 5 | 6 | export class GeoLongitudePropertyNameDetector extends PropertyNameDetectorBase { 7 | getApplicableTypes(): DPMPropertyTypes[] { 8 | return ["number"]; 9 | } 10 | 11 | getPropertyNameMatches(): RegExp[] { 12 | return [/^long$|longitude/i]; 13 | } 14 | 15 | getLabel(): string { 16 | return GEO_LONGITUDE_LABEL; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /client-lib/src/content-detector/Ipv4AddressDetector.ts: -------------------------------------------------------------------------------- 1 | import { RegexDetector } from "./RegexDetector"; 2 | 3 | export const IP_V4_ADDRESS_LABEL = "ip_v4_address"; 4 | 5 | /** Applies the 'phone_number' label when any single phone number is found in any value */ 6 | export class IpV4AddressDetector extends RegexDetector { 7 | getRegExp(): RegExp { 8 | return /(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/; 9 | } 10 | 11 | getLabel(): string { 12 | return IP_V4_ADDRESS_LABEL; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /client-lib/src/content-detector/NPIPropertyNameDetector.ts: -------------------------------------------------------------------------------- 1 | import { DPMPropertyTypes } from "datapm-lib"; 2 | import { PropertyNameDetectorBase } from "./PropertyNameDetectorBase"; 3 | 4 | export const NPI_LABEL = "national_provider_id"; 5 | export class NPIPropertyNameDetector extends PropertyNameDetectorBase { 6 | getApplicableTypes(): DPMPropertyTypes[] { 7 | return ["string", "integer"]; 8 | } 9 | 10 | getPropertyNameMatches(): RegExp[] { 11 | return [/^npi$|national[-_\s]?provider[-_\s]?id/i]; 12 | } 13 | 14 | getLabel(): string { 15 | return NPI_LABEL; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/content-detector/PassportPropertyNameDetector.ts: -------------------------------------------------------------------------------- 1 | import { DPMPropertyTypes } from "datapm-lib"; 2 | import { PropertyNameDetectorBase } from "./PropertyNameDetectorBase"; 3 | 4 | export const PASSPORT_LABEL = "passport"; 5 | export class PassportPropertyNameDetector extends PropertyNameDetectorBase { 6 | getApplicableTypes(): DPMPropertyTypes[] { 7 | return ["string", "integer"]; 8 | } 9 | 10 | getPropertyNameMatches(): RegExp[] { 11 | return [/pass[-_\s]?port/i]; 12 | } 13 | 14 | getLabel(): string { 15 | return PASSPORT_LABEL; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/content-detector/PasswordPropertyNameDetector.ts: -------------------------------------------------------------------------------- 1 | import { DPMPropertyTypes } from "datapm-lib"; 2 | import { PropertyNameDetectorBase } from "./PropertyNameDetectorBase"; 3 | 4 | export const SECRET_LABEL = "secret"; 5 | export class SecretPropertyNameDetector extends PropertyNameDetectorBase { 6 | getApplicableTypes(): DPMPropertyTypes[] { 7 | return ["string"]; 8 | } 9 | 10 | getPropertyNameMatches(): RegExp[] { 11 | return [/^pass$|password|secret/i]; 12 | } 13 | 14 | getLabel(): string { 15 | return SECRET_LABEL; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/content-detector/PhoneNumberDetector.ts: -------------------------------------------------------------------------------- 1 | import { RegexDetector } from "./RegexDetector"; 2 | 3 | export const PHONE_NUMBER_LABEL = "phone_number"; 4 | 5 | /** Applies the 'phone_number' label when any single phone number is found in any value */ 6 | export class PhoneNumberDetector extends RegexDetector { 7 | getApplicableTypes(): "string"[] { 8 | return ["string"]; 9 | } 10 | 11 | getRegExp(): RegExp { 12 | return /\b(?:\+?(\d{1,3})[-. (]+)?(\d{3})[-. )]+(\d{3})[-. ]+(\d{4})(?: *x(\d+))?\b/; 13 | } 14 | 15 | getLabel(): string { 16 | return PHONE_NUMBER_LABEL; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /client-lib/src/content-detector/UsernamePropertyNameDetector.ts: -------------------------------------------------------------------------------- 1 | import { PropertyNameDetectorBase } from "./PropertyNameDetectorBase"; 2 | 3 | export const USERNAME_LABEL = "username"; 4 | export class UsernamePropertyNameDetector extends PropertyNameDetectorBase { 5 | getApplicableTypes(): ("string" | "number" | "boolean" | "date" | "date-time")[] { 6 | return ["string"]; 7 | } 8 | 9 | getPropertyNameMatches(): RegExp[] { 10 | return [/user(?:[-_\s]name)?/i]; 11 | } 12 | 13 | getLabel(): string { 14 | return USERNAME_LABEL; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /client-lib/src/transforms/SpigetTransform.ts: -------------------------------------------------------------------------------- 1 | import { Transform, TransformCallback } from "stream"; 2 | 3 | export class SpigetTransform extends Transform { 4 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any 5 | _transform(chunk: any, encoding: BufferEncoding, callback: TransformCallback): void { 6 | callback(null, chunk); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /client-lib/src/types/bomstrip/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "bomstrip" { 2 | import { Readable, Transform } from "stream"; 3 | 4 | class BomStrippingStream extends Transform {} 5 | 6 | export = BomStrippingStream; 7 | } 8 | -------------------------------------------------------------------------------- /client-lib/src/types/buffer-peek-stream/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "buffer-peek-stream" { 2 | import { Readable } from "stream"; 3 | 4 | export function promise(stream: Readable, size: number): Promise<[Buffer, Readable]>; 5 | } 6 | -------------------------------------------------------------------------------- /client-lib/src/types/jsonstream-next/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "jsonstream-next" { 2 | import { Transform } from "stream"; 3 | 4 | export function parse( 5 | path: string, 6 | map?: (value: { [key: string]: unknown }) => { [key: string]: unknown } 7 | ): Transform; 8 | } 9 | -------------------------------------------------------------------------------- /client-lib/src/types/people-names/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "people-names" { 2 | export function parseNames(value: string): string[]; 3 | export function isPersonName(value: string): boolean; 4 | } 5 | -------------------------------------------------------------------------------- /client-lib/src/types/random-fruits-name/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "random-fruits-name" { 2 | function getRandomFruitsName(language: string, option?: { maxWords: number }): string; 3 | 4 | export = getRandomFruitsName; 5 | } 6 | -------------------------------------------------------------------------------- /client-lib/src/types/stream-fs-cache/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "stream-fs-cache" { 2 | import { Duplex, DuplexOptions } from "stream"; 3 | 4 | class StreamFsCache extends Duplex { 5 | constructor(path: string, opts?: DuplexOptions); 6 | } 7 | 8 | export = StreamFsCache; 9 | } 10 | -------------------------------------------------------------------------------- /client-lib/src/types/stream-mmmagic/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "stream-mmmagic" { 2 | import { Readable } from "stream"; 3 | export function promise( 4 | stream: Readable, 5 | options?: { 6 | magicFile?: string; 7 | splitMime?: boolean; 8 | peekBytes?: number; 9 | } 10 | ): Promise<[{ type: string; encoding: string }, Readable]>; 11 | } 12 | -------------------------------------------------------------------------------- /client-lib/src/types/unbzip2-stream/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "unbzip2-stream" { 2 | import { Readable, Transform } from "stream"; 3 | import through from "through"; 4 | 5 | function unbzip2Stream(): through.ThroughStream; 6 | export = unbzip2Stream; 7 | } 8 | -------------------------------------------------------------------------------- /client-lib/src/types/why-is-node-running/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "why-is-node-running" { 2 | function log(): void; 3 | export = log; 4 | } 5 | -------------------------------------------------------------------------------- /client-lib/src/types/xml-streamer/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "xml-streamer" { 2 | import { Readable, Transform } from "stream"; 3 | 4 | interface Opts { 5 | resourcePath?: string; 6 | emitOnNodeName?: boolean; 7 | attrsKey?: string; 8 | textKey?: string; 9 | explicitArray?: boolean; 10 | verbatimText?: boolean; 11 | } 12 | class XmlParser extends Transform { 13 | constructor(opts: Opts); 14 | } 15 | 16 | export = XmlParser; 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/util/LocalDataUtil.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import os from "os"; 3 | 4 | export function getLocalDataPath(catalogSlug: string | undefined, packageSlug: string): string { 5 | return path.join(os.homedir(), "datapm", "data", catalogSlug !== undefined ? catalogSlug : "_local", packageSlug); 6 | } 7 | -------------------------------------------------------------------------------- /client-lib/src/util/Maybe.ts: -------------------------------------------------------------------------------- 1 | export type Maybe = T | null; 2 | -------------------------------------------------------------------------------- /client-lib/src/util/ParsePackageIdentifierUtil.ts: -------------------------------------------------------------------------------- 1 | import { PackageIdentifierInput } from "../main"; 2 | 3 | export function parsePackageIdentifier(url: string): PackageIdentifierInput { 4 | const pathParts = url.split("/"); 5 | 6 | return { 7 | catalogSlug: pathParts[pathParts.length - 2], 8 | packageSlug: pathParts[pathParts.length - 1] 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /client-lib/src/util/Reference.ts: -------------------------------------------------------------------------------- 1 | /** For passing around a native value type that is updated and read in separate structures. 2 | * Helps detangle complex stream monitoring */ 3 | export class Reference { 4 | value: T; 5 | 6 | constructor(value: T) { 7 | this.value = value; 8 | } 9 | 10 | set(value: T): void { 11 | this.value = value; 12 | } 13 | 14 | get(): T { 15 | return this.value; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client-lib/src/util/RegistryReferenceUtil.ts: -------------------------------------------------------------------------------- 1 | import { PackageIdentifier } from "../generated/graphql"; 2 | 3 | export function packageString(packageIdentifier: PackageIdentifier): string { 4 | if (packageIdentifier.registryURL === "https://datapm.io") { 5 | return `${packageIdentifier.catalogSlug}/${packageIdentifier.packageSlug}`; 6 | } 7 | 8 | return `${packageIdentifier.registryURL}/${packageIdentifier.catalogSlug}/${packageIdentifier.packageSlug}`; 9 | } 10 | -------------------------------------------------------------------------------- /client/.bablerc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOpts": { 3 | "plugins": ["typescript", "flow"] 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /client/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | src/generated 4 | test/integration/registry-client.ts -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | pkg 5 | pkg* 6 | src/generated 7 | test/integration/registry-client.ts 8 | !*.datapm.json 9 | /*.datapm.json 10 | *.datapm.state.json 11 | !*.LICENSE.md 12 | /*.LICENSE.md 13 | !*.README.md 14 | /*.README.md 15 | datapm-state.json 16 | *state.json 17 | countries* 18 | *.csv 19 | test/credentials 20 | temp 21 | signing-certificiate.* 22 | temp 23 | *.msix 24 | *.p12 25 | *.pfx 26 | windows-installers 27 | *.crt 28 | *.cert 29 | *.pkg 30 | *.deb 31 | pkg-* 32 | 33 | installers/macos/macOS-x64/application 34 | installers/debian/build 35 | installers/redhat/build 36 | installers/windows/dist 37 | -------------------------------------------------------------------------------- /client/LICENSE: -------------------------------------------------------------------------------- 1 | datapm-lib by Travis Collins is licensed under CC BY-ND 4.0 CC -------------------------------------------------------------------------------- /client/assets/datapm-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/client/assets/datapm-logo.jpg -------------------------------------------------------------------------------- /client/installers/debian/changelog: -------------------------------------------------------------------------------- 1 | datapm-client (x.x.x-1) unstable; urgency=medium 2 | 3 | * Initial release 4 | 5 | -- Travis Collins Mon, 07 Feb 2022 20:47:48 +0000 -------------------------------------------------------------------------------- /client/installers/debian/control: -------------------------------------------------------------------------------- 1 | Source: datapm-client-source 2 | Version: x.x.x 3 | Package: datapm-client 4 | Homepage: https://datapm.io 5 | Maintainer: Travis Collins 6 | Architecture: amd64 7 | Description: DataPM is a package manager for data. See more at https://datapm.io 8 | DataPM is a package manager for data. You can publish packages to a registry, 9 | such as https://datapm.io (or host your own registry). You an consume pages 10 | and ETL them directly to a database, file system, or cloud storage system using 11 | the datapm client in this package. 12 | -------------------------------------------------------------------------------- /client/installers/debian/datapm-client.install: -------------------------------------------------------------------------------- 1 | ./debian/source/* ./opt/datapm -------------------------------------------------------------------------------- /client/installers/debian/datapm-client.links: -------------------------------------------------------------------------------- 1 | opt/datapm/datapm usr/bin/datapm 2 | -------------------------------------------------------------------------------- /client/installers/debian/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | DATAPM_LINK_LOCATION="/usr/bin/datapm" 6 | if [ -f $DATAPM_LINK_LOCATION ]; then 7 | rm -f $DATAPM_LINK_LOCATION 8 | fi 9 | 10 | ln -s /opt/datapm/datapm $DATAPM_LINK_LOCATION 11 | 12 | exit 0 -------------------------------------------------------------------------------- /client/installers/debian/prerm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | DATAPM_LINK_LOCATION="/opt/datapm" 6 | if [ -f $DATAPM_LINK_LOCATION ]; then 7 | rm -f $DATAPM_LINK_LOCATION 8 | fi 9 | 10 | exit 0 -------------------------------------------------------------------------------- /client/installers/macos/.gitignore: -------------------------------------------------------------------------------- 1 | macOS-x64/application 2 | -------------------------------------------------------------------------------- /client/installers/macos/README.md: -------------------------------------------------------------------------------- 1 | This is a heavily modified copy of the great work done by https://github.com/KosalaHerath/macos-installer-builder 2 | -------------------------------------------------------------------------------- /client/installers/macos/macOS-x64/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | application 3 | 4 | -------------------------------------------------------------------------------- /client/installers/macos/macOS-x64/darwin/Resources/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Visit https://datapm.io/docs/license to view the datapm license. -------------------------------------------------------------------------------- /client/installers/macos/macOS-x64/darwin/Resources/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/client/installers/macos/macOS-x64/darwin/Resources/banner.png -------------------------------------------------------------------------------- /client/installers/macos/macOS-x64/macos-runtime-entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.cs.disable-library-validation 6 | 7 | com.apple.security.cs.allow-unsigned-executable-memory 8 | 9 | 10 | -------------------------------------------------------------------------------- /client/installers/macos/utils/apple-logo-animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/client/installers/macos/utils/apple-logo-animation.gif -------------------------------------------------------------------------------- /client/installers/windows/README.md: -------------------------------------------------------------------------------- 1 | # Updating the SSL Certificate 2 | 3 | - Visit ssl.com and purchase a renewal of the signing certificate 4 | - After the certificate is approved, download the certificate and the private key - should be a p12 file format 5 | - The link is small and at the top right "Generate Certificate" 6 | - Base64 encode the file 7 | - openssl base64 -in .p12 -out .p12.base64 8 | - Copy the contents into the WINDOWS_CLIENT_CERTIFICATE_BASE64 in github secrets 9 | - Copy the password into the WINDOWS_CLIENT_CERTIFICATE_PASSWORD in github secrets 10 | 11 | 12 | -------------------------------------------------------------------------------- /client/src/command/Command.ts: -------------------------------------------------------------------------------- 1 | import { Argv } from "yargs"; 2 | 3 | export interface Command { 4 | prepareCommand(argv: Argv): Argv; 5 | } 6 | -------------------------------------------------------------------------------- /client/src/util/DefaultParameterOptions.ts: -------------------------------------------------------------------------------- 1 | import chalk from "chalk"; 2 | 3 | export const defaultPromptOptions = { 4 | onCancel: (): void => { 5 | console.log(chalk.red("User canceled")); 6 | process.exit(1); 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /client/test/packages/coinbase-btc-usd.LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | License not defined. Contact author. -------------------------------------------------------------------------------- /client/test/packages/coinbase-btc-usd.README.md: -------------------------------------------------------------------------------- 1 | # Coinbase BTC USD 2 | 3 | BTC USD ticks from coinbase -------------------------------------------------------------------------------- /client/test/packages/us-federal-it-standards.README.md: -------------------------------------------------------------------------------- 1 | # US Federal IT Standards 2 | 3 | This file is published on the GSA GitHub.com account. 4 | -------------------------------------------------------------------------------- /client/test/sources/countries-v1.csv: -------------------------------------------------------------------------------- 1 | "id","code","name","continent","wikipedia_link","keywords" 2 | 302672,"AD","Andorra","EU","https://en.wikipedia.org/wiki/Andorra", 3 | 302618,"AE","United Arab Emirates","AS","https://en.wikipedia.org/wiki/United_Arab_Emirates","UAE,مطارات في الإمارات العربية المتحدة" 4 | 302619,"AF","Afghanistan","AS","https://en.wikipedia.org/wiki/Afghanistan", 5 | 302722,"AG","Antigua and Barbuda","NA","https://en.wikipedia.org/wiki/Antigua_and_Barbuda", 6 | 302723,"AI","Anguilla","NA","https://en.wikipedia.org/wiki/Anguilla", -------------------------------------------------------------------------------- /client/test/sources/covid-02-01-2020.avro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/client/test/sources/covid-02-01-2020.avro -------------------------------------------------------------------------------- /client/test/sources/non-profits-1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/client/test/sources/non-profits-1.zip -------------------------------------------------------------------------------- /client/test/sources/non-profits-2-4.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/client/test/sources/non-profits-2-4.zip -------------------------------------------------------------------------------- /client/test/sources/source.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/client/test/sources/source.tar -------------------------------------------------------------------------------- /client/test/sources/source.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/client/test/sources/source.zip -------------------------------------------------------------------------------- /client/test/sources/state-codes.csv.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/client/test/sources/state-codes.csv.bz2 -------------------------------------------------------------------------------- /client/test/sources/state-codes.csv.gzip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/client/test/sources/state-codes.csv.gzip -------------------------------------------------------------------------------- /client/test/sources/us-covid.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/client/test/sources/us-covid.xlsx -------------------------------------------------------------------------------- /client/test/sources/weird-headers.csv: -------------------------------------------------------------------------------- 1 | normal,exclamation!,questionMark? 2 | normal,exclamation,questionMark 3 | -------------------------------------------------------------------------------- /client/test/test-data-server.ts: -------------------------------------------------------------------------------- 1 | /** A small test server for http request testing */ 2 | import express from "express"; 3 | import fs from "fs"; 4 | 5 | const app = express(); 6 | 7 | const port = process.env.PORT || 2999; 8 | 9 | app.use("/state-codes.csv", function (req, res) { 10 | res.set("content-type", "text/csv"); 11 | res.send(fs.readFileSync("test/sources/state-codes.csv")); 12 | }); 13 | 14 | app.listen({ port }, () => { 15 | console.log(`🚀 Test Data Server ready at http://localhost:${port}`); 16 | }); 17 | -------------------------------------------------------------------------------- /docker/Docker-env: -------------------------------------------------------------------------------- 1 | PORT=4000 2 | REGISTRY_NAME="DataPM Local Docker" 3 | REGISTRY_URL=http://localhost:4000 4 | JWT_KEY=!!!!REPLACE_ME!!! 5 | STORAGE_URL="file:///var/lib/datapm-registry/data" 6 | TYPEORM_PORT=5432 7 | TYPEORM_HOST=postgres 8 | TYPEORM_DATABASE=datapm 9 | TYPEORM_SCHEMA=public 10 | TYPEORM_USERNAME=postgres 11 | TYPEORM_PASSWORD=postgres 12 | SMTP_SERVER=smtp 13 | SMTP_PORT=25 14 | SMTP_USER= 15 | SMTP_PASSWORD= 16 | SMTP_FROM_NAME="Localhost DataPM Registry" 17 | SMTP_FROM_ADDRESS="datapm@localhost" 18 | SMTP_SECURE=false 19 | ALLOW_WEB_CRAWLERS=false -------------------------------------------------------------------------------- /docker/Dockerfile-client: -------------------------------------------------------------------------------- 1 | # To build, run the following command from the root of the repository: 2 | # docker buildx build --platform linux/amd64 -t datapm/client:latest -f docker/Dockerfile-client . 3 | 4 | FROM debian:bullseye-slim 5 | 6 | COPY client-installers/datapm-client*.deb /usr/src/app/client-installers/ 7 | 8 | WORKDIR /usr/src/app/client-installers/ 9 | 10 | RUN dpkg -i *.deb 11 | 12 | RUN rm -rf /usr/src/app/client-installers/ 13 | 14 | ENTRYPOINT [ "datapm" ] -------------------------------------------------------------------------------- /docker/init-database.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | psql -U postgres -c 'select 1' -d $POSTGRES_DB &>dev/null || psql -U postgres -tc 'create database $POSTGRES_DB' -------------------------------------------------------------------------------- /docs/.dockerignore: -------------------------------------------------------------------------------- 1 | */node_modules 2 | *.log 3 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | node_modules 4 | 5 | lib/core/metadata.js 6 | lib/core/MetadataBlog.js 7 | 8 | website/translated_docs 9 | website/build/ 10 | website/yarn.lock 11 | website/node_modules 12 | website/i18n/* 13 | -------------------------------------------------------------------------------- /docs/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:lts 2 | 3 | WORKDIR /app/website 4 | 5 | EXPOSE 3000 35729 6 | COPY ./docs /app/docs 7 | COPY ./website /app/website 8 | RUN yarn install 9 | 10 | CMD ["yarn", "start"] 11 | -------------------------------------------------------------------------------- /docs/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | docusaurus: 5 | build: . 6 | ports: 7 | - 3000:3000 8 | - 35729:35729 9 | volumes: 10 | - ./docs:/app/docs 11 | - ./website/blog:/app/website/blog 12 | - ./website/core:/app/website/core 13 | - ./website/i18n:/app/website/i18n 14 | - ./website/pages:/app/website/pages 15 | - ./website/static:/app/website/static 16 | - ./website/sidebars.json:/app/website/sidebars.json 17 | - ./website/siteConfig.js:/app/website/siteConfig.js 18 | working_dir: /app/website 19 | -------------------------------------------------------------------------------- /docs/website/.gitignore: -------------------------------------------------------------------------------- 1 | ./build 2 | ./i18n 3 | -------------------------------------------------------------------------------- /docs/website/gulpfile.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | function clean() { 4 | return new Promise((resolve) => { 5 | if (fs.existsSync("build")) fs.rmSync("build", { recursive: true, force: true }); 6 | 7 | resolve(); 8 | }); 9 | } 10 | 11 | 12 | exports.clean = clean; 13 | -------------------------------------------------------------------------------- /docs/website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "clean": "gulp clean", 4 | "examples": "docusaurus-examples", 5 | "start": "docusaurus-start", 6 | "prebuild": "npm run clean", 7 | "build": "docusaurus-build", 8 | "publish-gh-pages": "docusaurus-publish", 9 | "write-translations": "docusaurus-write-translations", 10 | "version": "docusaurus-version", 11 | "rename-version": "docusaurus-rename-version" 12 | }, 13 | "devDependencies": { 14 | "docusaurus": "^1.14.6", 15 | "gulp": "^4.0.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /docs/website/sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "docs": { 3 | "Overview": [ 4 | "quick-start", 5 | "concepts", 6 | "about", 7 | "unclaimed-listings", 8 | "license" 9 | ], 10 | "Use Cases": [ 11 | "find-data", 12 | "publish-data", 13 | "organize-data", 14 | "devops" 15 | ], 16 | "Documentation": [ 17 | "command-line-client", 18 | "package-files", 19 | "connectors", 20 | "access-control", 21 | "registry-api", 22 | "private-registry" 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /docs/website/static/font/static/Roboto-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/docs/website/static/font/static/Roboto-Black.ttf -------------------------------------------------------------------------------- /docs/website/static/font/static/Roboto-BlackItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/docs/website/static/font/static/Roboto-BlackItalic.ttf -------------------------------------------------------------------------------- /docs/website/static/font/static/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/docs/website/static/font/static/Roboto-Bold.ttf -------------------------------------------------------------------------------- /docs/website/static/font/static/Roboto-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/docs/website/static/font/static/Roboto-BoldItalic.ttf -------------------------------------------------------------------------------- /docs/website/static/font/static/Roboto-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/docs/website/static/font/static/Roboto-Italic.ttf -------------------------------------------------------------------------------- /docs/website/static/font/static/Roboto-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/docs/website/static/font/static/Roboto-Light.ttf -------------------------------------------------------------------------------- /docs/website/static/font/static/Roboto-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/docs/website/static/font/static/Roboto-LightItalic.ttf -------------------------------------------------------------------------------- /docs/website/static/font/static/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/docs/website/static/font/static/Roboto-Medium.ttf -------------------------------------------------------------------------------- /docs/website/static/font/static/Roboto-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/docs/website/static/font/static/Roboto-MediumItalic.ttf -------------------------------------------------------------------------------- /docs/website/static/font/static/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/docs/website/static/font/static/Roboto-Regular.ttf -------------------------------------------------------------------------------- /docs/website/static/font/static/Roboto-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/docs/website/static/font/static/Roboto-Thin.ttf -------------------------------------------------------------------------------- /docs/website/static/font/static/Roboto-ThinItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/docs/website/static/font/static/Roboto-ThinItalic.ttf -------------------------------------------------------------------------------- /docs/website/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/docs/website/static/img/favicon.ico -------------------------------------------------------------------------------- /docs/website/static/img/oss_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/docs/website/static/img/oss_logo.png -------------------------------------------------------------------------------- /docs/website/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | DataPM Documentation 10 | 11 | 12 | If you are not redirected automatically, follow this 13 | link. 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/website/static/load-theme-options.js: -------------------------------------------------------------------------------- 1 | const theme = localStorage.getItem("THEME"); 2 | const themeClass = theme === "DARK" ? "theme-dark" : "theme-light"; 3 | window.onload = () => document.body.classList.add(themeClass); -------------------------------------------------------------------------------- /frontend/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /frontend/.prettierrc.yaml: -------------------------------------------------------------------------------- 1 | # Reference: https://prettier.io/docs/en/options.html 2 | 3 | tabWidth: 4 4 | useTabs: false 5 | printWidth: 120 6 | 7 | trailingComma: none 8 | bracketSpacing: true 9 | jsxBracketSameLine: true 10 | 11 | semi: true 12 | arrowParens: always 13 | singleQuote: false 14 | -------------------------------------------------------------------------------- /frontend/e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from "protractor"; 2 | 3 | export class AppPage { 4 | navigateTo(): Promise { 5 | return browser.get(browser.baseUrl) as Promise; 6 | } 7 | 8 | getTitleText(): Promise { 9 | return element(by.css("app-root .content span")).getText() as Promise; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /frontend/e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../tsconfig.base.json", 4 | "compilerOptions": { 5 | "outDir": "../out-tsc/e2e", 6 | "module": "commonjs", 7 | "target": "es2018", 8 | "types": ["jasmine", "jasminewd2", "node"] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 | 7 |
8 | 9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /frontend/src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | .container-fluid { 2 | overflow-x: hidden; 3 | } 4 | 5 | @media (min-width: 576px) { 6 | .container, 7 | .container-sm { 8 | max-width: 570px !important; 9 | } 10 | } 11 | 12 | @media (max-width: 576px) { 13 | .content { 14 | padding-bottom: 50px !important; 15 | } 16 | } 17 | 18 | .content { 19 | min-height: 500px; 20 | padding-bottom: 100px; 21 | } 22 | -------------------------------------------------------------------------------- /frontend/src/app/catalog/catalog-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from "@angular/core"; 2 | import { Routes, RouterModule } from "@angular/router"; 3 | import { CatalogComponent } from "./catalog/catalog.component"; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: ":catalogSlug", 8 | component: CatalogComponent 9 | } 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule] 15 | }) 16 | export class CatalogRoutingModule {} 17 | -------------------------------------------------------------------------------- /frontend/src/app/catalog/catalog/catalog.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: flex; 3 | min-height: 300px; 4 | align-items: center; 5 | justify-content: center; 6 | } 7 | 8 | .page-content { 9 | width: 100%; 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/app/catalog/user-details-page/user-details-page.component.scss: -------------------------------------------------------------------------------- 1 | .fixed-height { 2 | min-height: 450px; 3 | } 4 | 5 | .user-routes { 6 | padding: 0px 16px; 7 | } 8 | 9 | @media (max-width: 576px) { 10 | .fixed-height { 11 | min-height: 300px; 12 | } 13 | .user-routes { 14 | padding: 0px 0px 0px 4px; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/app/collection-details/collection-details-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from "@angular/core"; 2 | import { Routes, RouterModule } from "@angular/router"; 3 | 4 | import { CollectionDetailsComponent } from "./collection-details/collection-details.component"; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: "", 9 | component: CollectionDetailsComponent 10 | } 11 | ]; 12 | 13 | @NgModule({ 14 | imports: [RouterModule.forChild(routes)], 15 | exports: [RouterModule] 16 | }) 17 | export class CollectionDetailsRoutingModule {} 18 | -------------------------------------------------------------------------------- /frontend/src/app/collection-details/collection-details/collection-followers/collection-followers.component.html: -------------------------------------------------------------------------------- 1 |
2 | 10 |
11 | -------------------------------------------------------------------------------- /frontend/src/app/downloads/downloads-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from "@angular/core"; 2 | import { Routes, RouterModule } from "@angular/router"; 3 | import { DownloadsComponent } from "./downloads.component"; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: "", 8 | component: DownloadsComponent 9 | } 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule] 15 | }) 16 | export class DownloadsRoutingModule {} 17 | -------------------------------------------------------------------------------- /frontend/src/app/downloads/downloads.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/app/downloads/downloads.component.scss -------------------------------------------------------------------------------- /frontend/src/app/downloads/downloads.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { DATAPM_VERSION } from 'datapm-lib'; 3 | 4 | @Component({ 5 | selector: 'app-downloads', 6 | templateUrl: './downloads.component.html', 7 | styleUrls: ['./downloads.component.scss'] 8 | }) 9 | export class DownloadsComponent implements OnInit { 10 | 11 | public version = DATAPM_VERSION; 12 | 13 | constructor() { 14 | console.log("testing") 15 | } 16 | 17 | ngOnInit(): void { 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /frontend/src/app/downloads/downloads.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { DownloadsComponent } from './downloads.component'; 4 | import { DownloadsRoutingModule } from "./downloads-routing.module" 5 | 6 | 7 | @NgModule({ 8 | declarations: [DownloadsComponent], 9 | imports: [ 10 | CommonModule, 11 | DownloadsRoutingModule 12 | ] 13 | }) 14 | export class DownloadsModule { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/app/group/group-manage/group-manage.component.html: -------------------------------------------------------------------------------- 1 |
2 |
Manage Group
3 | 4 | 7 |
8 | -------------------------------------------------------------------------------- /frontend/src/app/group/group-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from "@angular/core"; 2 | import { Routes, RouterModule } from "@angular/router"; 3 | import { GroupDetailsComponent } from "./group-details/group-details.component"; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: "", 8 | component: GroupDetailsComponent 9 | } 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule] 15 | }) 16 | export class GroupRoutingModule {} 17 | -------------------------------------------------------------------------------- /frontend/src/app/helpers/IdentifierHelper.ts: -------------------------------------------------------------------------------- 1 | import { PackageIdentifierInput } from "../../../src/generated/graphql"; 2 | import { getRegistryHostname, getRegistryURL } from "./RegistryAccessHelper"; 3 | 4 | export function packageToIdentifier(identifier: PackageIdentifierInput) { 5 | const hostname = getRegistryHostname(); 6 | 7 | if (hostname == "datapm.io" || hostname == "www.datapm.io") 8 | return identifier.catalogSlug + "/" + identifier.packageSlug; 9 | 10 | return getRegistryURL() + "/" + identifier.catalogSlug + "/" + identifier.packageSlug; 11 | } 12 | -------------------------------------------------------------------------------- /frontend/src/app/helpers/RegistryAccessHelper.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, inject } from "@angular/core/testing"; 2 | 3 | import * as RegistryAccessHelper from "./RegistryAccessHelper"; 4 | import { RouterTestingModule } from "@angular/router/testing"; 5 | -------------------------------------------------------------------------------- /frontend/src/app/helpers/utils.ts: -------------------------------------------------------------------------------- 1 | export function extractErrorMsg(error: any) { 2 | if (error.networkError?.error.errors) { 3 | return error.networkError?.error.errors[0].message; 4 | } else if (error.errors) { 5 | return error.errors[0].message; 6 | } 7 | 8 | return "Unknown error occured"; 9 | } 10 | -------------------------------------------------------------------------------- /frontend/src/app/home/admin-dashboard/admin-dashboard.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/app/home/admin-dashboard/admin-dashboard.component.scss -------------------------------------------------------------------------------- /frontend/src/app/home/admin-dashboard/admin-dashboard.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | 3 | @Component({ 4 | selector: "app-admin-dashboard", 5 | templateUrl: "./admin-dashboard.component.html", 6 | styleUrls: ["./admin-dashboard.component.scss"] 7 | }) 8 | export class AdminDashboardComponent { 9 | private readonly URL_PREFIX = "/admin"; 10 | 11 | public routes = [ 12 | { linkName: "users", url: this.URL_PREFIX + "/users" }, 13 | { linkName: "groups", url: this.URL_PREFIX + "/groups" }, 14 | { linkName: "platform settings", url: this.URL_PREFIX + "/platform-settings" } 15 | ]; 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/app/home/admin-dashboard/groups/admin-status-confirmation/admin-status-confirmation.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/app/home/admin-dashboard/groups/admin-status-confirmation/admin-status-confirmation.component.scss -------------------------------------------------------------------------------- /frontend/src/app/home/admin-dashboard/users/admin-status-confirmation/admin-status-confirmation.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/app/home/admin-dashboard/users/admin-status-confirmation/admin-status-confirmation.component.scss -------------------------------------------------------------------------------- /frontend/src/app/home/homepage/homepage.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/app/home/homepage/homepage.component.scss -------------------------------------------------------------------------------- /frontend/src/app/home/recently-viewed/recently-viewed.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/app/home/recently-viewed/recently-viewed.component.scss -------------------------------------------------------------------------------- /frontend/src/app/home/trending/trending.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from "@angular/core"; 2 | 3 | @Component({ 4 | selector: "trending", 5 | templateUrl: "./trending.component.html", 6 | styleUrls: ["./trending.component.scss"] 7 | }) 8 | export class TrendingComponent implements OnInit { 9 | public isFavorite = false; 10 | 11 | constructor() {} 12 | 13 | ngOnInit(): void {} 14 | 15 | public makeFavorite(): void { 16 | this.isFavorite = !this.isFavorite; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /frontend/src/app/imported/builder-io-component/builder-io-renderer/builder-io-renderer.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /frontend/src/app/imported/builder-io-component/builder-io-renderer/builder-io-renderer.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/app/imported/builder-io-component/builder-io-renderer/builder-io-renderer.component.scss -------------------------------------------------------------------------------- /frontend/src/app/imported/builder-io-component/builder-io.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /frontend/src/app/imported/builder-io-component/builder-io.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/app/imported/builder-io-component/builder-io.component.scss -------------------------------------------------------------------------------- /frontend/src/app/imported/imported.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from "@angular/core"; 2 | import { CommonModule } from "@angular/common"; 3 | import { BuilderIOComponent } from "./builder-io-component/builder-io.component"; 4 | import { SafeHtmlPipe } from "./safe-html.pipe"; 5 | import { BuilderIoRendererComponent } from "./builder-io-component/builder-io-renderer/builder-io-renderer.component"; 6 | 7 | @NgModule({ 8 | declarations: [BuilderIOComponent, SafeHtmlPipe, BuilderIoRendererComponent], 9 | imports: [CommonModule], 10 | exports: [BuilderIOComponent, BuilderIoRendererComponent] 11 | }) 12 | export class ImportedModule {} 13 | -------------------------------------------------------------------------------- /frontend/src/app/imported/safe-html.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from "@angular/core"; 2 | import { DomSanitizer, SafeHtml } from "@angular/platform-browser"; 3 | 4 | @Pipe({ 5 | name: "safeHtml" 6 | }) 7 | export class SafeHtmlPipe implements PipeTransform { 8 | constructor(private sanitizer: DomSanitizer) {} 9 | 10 | public transform(style: string): SafeHtml { 11 | return this.sanitizer.bypassSecurityTrustHtml(style); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/app/json-typings.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.json" { 2 | const value: any; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /frontend/src/app/login-container/login-container-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from "@angular/core"; 2 | import { Routes, RouterModule } from "@angular/router"; 3 | 4 | import { LoginContainerComponent } from "./login-container.component"; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: "", 9 | component: LoginContainerComponent 10 | } 11 | ]; 12 | 13 | @NgModule({ 14 | imports: [RouterModule.forChild(routes)], 15 | exports: [RouterModule] 16 | }) 17 | export class LoginContainerRoutingModule {} 18 | -------------------------------------------------------------------------------- /frontend/src/app/login-container/login-container.component.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /frontend/src/app/login-container/login-container.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/app/login-container/login-container.component.scss -------------------------------------------------------------------------------- /frontend/src/app/markdown-options.ts: -------------------------------------------------------------------------------- 1 | import { MarkedOptions, MarkedRenderer } from "ngx-markdown"; 2 | 3 | export function buildMarkedOptionsFactory(): MarkedOptions { 4 | const renderer = new MarkedRenderer(); 5 | 6 | renderer.blockquote = (text: string) => { 7 | return "

" + text + "

"; 8 | }; 9 | 10 | return { 11 | renderer: renderer, 12 | gfm: true, 13 | breaks: false, 14 | pedantic: false, 15 | smartLists: true, 16 | smartypants: false 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /frontend/src/app/models/page-state.ts: -------------------------------------------------------------------------------- 1 | export type PageState = "INIT" | "LOADING" | "SUCCESS" | "ERROR"; 2 | -------------------------------------------------------------------------------- /frontend/src/app/models/tab.model.ts: -------------------------------------------------------------------------------- 1 | export interface TabModel { 2 | name: string; 3 | value: string; 4 | } 5 | -------------------------------------------------------------------------------- /frontend/src/app/package/components/package-followers/package-followers.component.html: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /frontend/src/app/package/components/package-info/Inspecting public_150k_plus_220703.csv.md: -------------------------------------------------------------------------------- 1 | Inspecting public_150k_plus_220703.csv 2 | - 8k records counted 3 | - 8k records inspected 4 | - 4.0MB processed 5 | - 3k records/second 6 | 7 | 27 seconds remaining 8 | Press Ctrl+C to stop inspecting -------------------------------------------------------------------------------- /frontend/src/app/package/components/package-info/edit-website-dialog/edit-website-dialog.component.scss: -------------------------------------------------------------------------------- 1 | #editWebsite { 2 | ::ng-deep { 3 | .rounded-input { 4 | .dpm-input-square { 5 | border-radius: 6px; 6 | padding: 7px 10px; 7 | height: unset; 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /frontend/src/app/package/components/package-samples/package-samples.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../../styles/variables"; 2 | @import "../../../../styles/colors"; 3 | 4 | .samples { 5 | width: 100%; 6 | height: 331px; 7 | display: block; 8 | border-radius: 4px; 9 | } 10 | 11 | .subtitle { 12 | margin-bottom: 10px; 13 | } 14 | 15 | a { 16 | color: var(--info-color) !important; 17 | cursor: pointer; 18 | } 19 | -------------------------------------------------------------------------------- /frontend/src/app/package/components/package-version/package-version.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../../styles/variables"; 2 | 3 | table { 4 | .history-ul { 5 | margin-bottom: 0px !important; 6 | } 7 | .second-tr { 8 | border-bottom: 1px solid var(--gray-9-color); 9 | padding: 16px 0px 0px 0px; 10 | &:last-child { 11 | border: none; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /frontend/src/app/package/components/package-version/version-comparison-modal/version-comparison-modal.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../../../styles/variables"; 2 | 3 | ul { 4 | padding-left: 20px; 5 | } 6 | -------------------------------------------------------------------------------- /frontend/src/app/package/components/package-version/version-comparison-modal/version-comparison-model.ts: -------------------------------------------------------------------------------- 1 | import { PackageIdentifierInput, Version, VersionIdentifier } from "src/generated/graphql"; 2 | 3 | export interface VersionComparisonModel { 4 | packageIdentifier: PackageIdentifierInput; 5 | newVersion: VersionIdentifier; 6 | oldVersion: VersionIdentifier; 7 | versions: Version[]; 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/app/package/pipes/package-size.pipe.spec.ts: -------------------------------------------------------------------------------- 1 | import { PackageSizePipe } from "./package-size.pipe"; 2 | 3 | describe("PackageSizePipe", () => { 4 | it("create an instance", () => { 5 | const pipe = new PackageSizePipe(); 6 | expect(pipe).toBeTruthy(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /frontend/src/app/package/pipes/schema-properties.pipe.spec.ts: -------------------------------------------------------------------------------- 1 | import { SchemaPropertiesPipe } from "./schema-properties.pipe"; 2 | 3 | describe("SchemaPropertiesPipe", () => { 4 | it("create an instance", () => { 5 | const pipe = new SchemaPropertiesPipe(); 6 | expect(pipe).toBeTruthy(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /frontend/src/app/package/pipes/schema-properties.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from "@angular/core"; 2 | import { Property, Schema } from "datapm-lib"; 3 | 4 | @Pipe({ 5 | name: "schemaProperties" 6 | }) 7 | export class SchemaPropertiesPipe implements PipeTransform { 8 | transform(value: Schema): Property[] { 9 | return Object.values(value?.properties); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /frontend/src/app/package/pipes/version.pipe.spec.ts: -------------------------------------------------------------------------------- 1 | import { VersionPipe } from "./version.pipe"; 2 | 3 | describe("VersionPipe", () => { 4 | it("create an instance", () => { 5 | const pipe = new VersionPipe(); 6 | expect(pipe).toBeTruthy(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /frontend/src/app/package/pipes/version.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from "@angular/core"; 2 | import { VersionIdentifier } from "src/generated/graphql"; 3 | 4 | @Pipe({ 5 | name: "version" 6 | }) 7 | export class VersionPipe implements PipeTransform { 8 | transform(value: VersionIdentifier): string { 9 | if (!value) { 10 | return ""; 11 | } 12 | 13 | return `${value.versionMajor}.${value.versionMinor}.${value.versionPatch}`; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /frontend/src/app/package/services/package-resolver.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from "@angular/core/testing"; 2 | 3 | import { PackageResolverService } from "./package-resolver.service"; 4 | 5 | describe("PackageResolverService", () => { 6 | let service: PackageResolverService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(PackageResolverService); 11 | }); 12 | 13 | it("should be created", () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /frontend/src/app/package/services/package.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from "@angular/core/testing"; 2 | 3 | import { PackageService } from "./package.service"; 4 | 5 | describe("PackageService", () => { 6 | let service: PackageService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(PackageService); 11 | }); 12 | 13 | it("should be created", () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /frontend/src/app/search/search-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from "@angular/core"; 2 | import { Routes, RouterModule } from "@angular/router"; 3 | import { SearchComponent } from "./search.component"; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: "", 8 | component: SearchComponent 9 | } 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule] 15 | }) 16 | export class SearchRoutingModule {} 17 | -------------------------------------------------------------------------------- /frontend/src/app/search/search.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../styles/variables"; 2 | @import "../../styles/colors"; 3 | 4 | .padding-desktop { 5 | padding: 50px 30px; 6 | } 7 | 8 | .search-icon { 9 | font-size: 40px; 10 | color: var(--gray-1-color); 11 | } 12 | 13 | p { 14 | margin-bottom: 10px; 15 | } 16 | 17 | @media (max-width: 992px) { 18 | .padding-desktop { 19 | padding: 10px 0px !important; 20 | } 21 | } 22 | 23 | @media (max-width: 576px) { 24 | .padding-desktop { 25 | padding: 10px 15px !important; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /frontend/src/app/services/dialog/confirmation-dialog-config.ts: -------------------------------------------------------------------------------- 1 | import { ConfirmationDialogData } from "./confirmation-dialog-data"; 2 | import { DialogSize } from "./dialog-size"; 3 | 4 | export interface ConfirmationDialogConfig { 5 | data: ConfirmationDialogData; 6 | size?: DialogSize; 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/app/services/dialog/confirmation-dialog-data.ts: -------------------------------------------------------------------------------- 1 | import { DialogTextOrientation } from "./dialog-text-orientation"; 2 | 3 | export interface ConfirmationDialogData { 4 | title: string; 5 | content: string; 6 | warning?: string; 7 | showConfirmationInputField?: boolean; 8 | confirmationInputFieldRequiredValue?: string; 9 | confirmButtonText?: string; 10 | cancelButtonText?: string; 11 | textOrientation?: DialogTextOrientation; 12 | } 13 | -------------------------------------------------------------------------------- /frontend/src/app/services/dialog/dialog-config.ts: -------------------------------------------------------------------------------- 1 | import { DialogSize } from "./dialog-size"; 2 | 3 | export interface DialogConfig { 4 | data: any; 5 | size?: DialogSize; 6 | } 7 | -------------------------------------------------------------------------------- /frontend/src/app/services/dialog/dialog-dimensions.ts: -------------------------------------------------------------------------------- 1 | export interface DialogDimensions { 2 | x: number; 3 | y: number; 4 | } 5 | -------------------------------------------------------------------------------- /frontend/src/app/services/dialog/dialog-size.ts: -------------------------------------------------------------------------------- 1 | export enum DialogSize { 2 | SMALL, 3 | MEDIUM, 4 | LARGE, 5 | X_LARGE 6 | } 7 | -------------------------------------------------------------------------------- /frontend/src/app/services/dialog/dialog-text-orientation.ts: -------------------------------------------------------------------------------- 1 | export enum DialogTextOrientation { 2 | LEFT = "left", 3 | CENTER = "center", 4 | RIGHT = "right" 5 | } 6 | -------------------------------------------------------------------------------- /frontend/src/app/services/dialog/dialog.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from "@angular/core/testing"; 2 | 3 | import { DialogService } from "./dialog.service"; 4 | 5 | describe("DialogService", () => { 6 | let service: DialogService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(DialogService); 11 | }); 12 | 13 | it("should be created", () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /frontend/src/app/services/dialog/user-status-change-dialog-response.ts: -------------------------------------------------------------------------------- 1 | import { UserStatus } from "src/generated/graphql"; 2 | 3 | export interface UserStatusChangeDialogResponse { 4 | status: UserStatus; 5 | message: string; 6 | } 7 | -------------------------------------------------------------------------------- /frontend/src/app/services/file.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from "@angular/core/testing"; 2 | 3 | import { FileService } from "./file.service"; 4 | 5 | describe("FileService", () => { 6 | let service: FileService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(FileService); 11 | }); 12 | 13 | it("should be created", () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /frontend/src/app/services/image.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from "@angular/core/testing"; 2 | import { HttpClientModule } from "@angular/common/http"; 3 | 4 | import { ImageService } from "./image.service"; 5 | 6 | describe("ImageService", () => { 7 | let service: ImageService; 8 | 9 | beforeEach(() => { 10 | TestBed.configureTestingModule({ 11 | imports: [HttpClientModule] 12 | }); 13 | service = TestBed.inject(ImageService); 14 | }); 15 | 16 | it("should be created", () => { 17 | expect(service).toBeTruthy(); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /frontend/src/app/services/snackBar.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import { MatSnackBar } from "@angular/material/snack-bar"; 3 | 4 | @Injectable({ 5 | providedIn: "root" 6 | }) 7 | export class SnackBarService { 8 | //create an instance of MatSnackBar 9 | 10 | constructor(private snackBar: MatSnackBar) {} 11 | 12 | /* It takes three parameters 13 | 1.the message string 14 | 2.the action 15 | 3.the duration, alignment, etc. */ 16 | 17 | openSnackBar(message: string, action: string) { 18 | this.snackBar.open(message, action, { 19 | duration: 2000 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /frontend/src/app/services/ui-style-toggle.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from "@angular/core/testing"; 2 | 3 | import { UiStyleToggleService } from "./ui-style-toggle.service"; 4 | 5 | describe("UiStyleToggleService", () => { 6 | let service: UiStyleToggleService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(UiStyleToggleService); 11 | }); 12 | 13 | it("should be created", () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /frontend/src/app/shared/catalog-autocomplete/catalog-autocomplete.component.scss: -------------------------------------------------------------------------------- 1 | .mat-option { 2 | height: 75px; 3 | padding: 5px 10px; 4 | line-height: 75px; 5 | 6 | ::ng-deep.avatar { 7 | line-height: 20px; 8 | margin-right: 10px; 9 | } 10 | } -------------------------------------------------------------------------------- /frontend/src/app/shared/collection-autocomplete/collection-autocomplete.component.scss: -------------------------------------------------------------------------------- 1 | .mat-option { 2 | height: 75px; 3 | padding: 5px 10px; 4 | line-height: 75px; 5 | 6 | ::ng-deep.avatar { 7 | line-height: 20px; 8 | margin-right: 10px; 9 | } 10 | } -------------------------------------------------------------------------------- /frontend/src/app/shared/command-modal/fetch/fetch-modal.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
-------------------------------------------------------------------------------- /frontend/src/app/shared/command-modal/fetch/fetch-modal.component.scss: -------------------------------------------------------------------------------- 1 | 2 | :host { 3 | height: 100%; 4 | display: flex; 5 | flex-direction: column; 6 | } 7 | -------------------------------------------------------------------------------- /frontend/src/app/shared/command-modal/package/package-modal.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
-------------------------------------------------------------------------------- /frontend/src/app/shared/command-modal/package/package-modal.component.scss: -------------------------------------------------------------------------------- 1 | 2 | :host { 3 | height: 100%; 4 | display: flex; 5 | flex-direction: column; 6 | } 7 | -------------------------------------------------------------------------------- /frontend/src/app/shared/command-modal/update/update-modal.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/app/shared/command-modal/update/update-modal.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/app/shared/command-modal/update/update-modal.component.scss -------------------------------------------------------------------------------- /frontend/src/app/shared/confirmation-dialog/confirmation-dialog.component.html: -------------------------------------------------------------------------------- 1 |
2 |
{{ data }}
3 |
4 |
5 | 6 |
7 | -------------------------------------------------------------------------------- /frontend/src/app/shared/confirmation-dialog/confirmation-dialog.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../styles/variables"; 2 | @import "../../../styles/colors"; 3 | 4 | .mat-dialog-content { 5 | max-width: 500px; 6 | font-family: $family-roboto; 7 | font-style: $style-normal; 8 | font-weight: $weight-400; 9 | font-size: $text-font; 10 | line-height: 18px; 11 | letter-spacing: 0.4px; 12 | color: var(--gray-2-color); 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/app/shared/confirmation-dialog/confirmation-dialog.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Inject, OnInit } from "@angular/core"; 2 | import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; 3 | 4 | @Component({ 5 | selector: "app-confirmation-dialog", 6 | templateUrl: "./confirmation-dialog.component.html", 7 | styleUrls: ["./confirmation-dialog.component.scss"] 8 | }) 9 | export class ConfirmationDialogComponent implements OnInit { 10 | constructor(@Inject(MAT_DIALOG_DATA) public data: string) {} 11 | 12 | ngOnInit(): void {} 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/app/shared/cover/cover.component.html: -------------------------------------------------------------------------------- 1 |
2 | cover 3 | 6 |
7 | -------------------------------------------------------------------------------- /frontend/src/app/shared/followers/followers.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../styles/_colors.scss"; 2 | @import "../../../styles/_variables.scss"; 3 | 4 | .height-17 { 5 | line-height: 17px; 6 | } 7 | 8 | .col-lg-4 { 9 | padding-left: 0px; 10 | &:nth-child(3n + 1) { 11 | padding-right: 0px; 12 | } 13 | } 14 | 15 | @media (max-width: 992px) { 16 | .col-lg-4 { 17 | &:nth-child(2n + 1) { 18 | padding-right: 0px; 19 | } 20 | } 21 | } 22 | 23 | @media (max-width: 767px) { 24 | .col-lg-4 { 25 | padding-right: 0px; 26 | } 27 | .show-more-btn { 28 | padding: 0px; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /frontend/src/app/shared/footer/footer.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../styles/variables"; 2 | @import "../../../styles/colors"; 3 | 4 | .footer-bg { 5 | padding: 20px 15px 20px 15px; 6 | width: 100%; 7 | } 8 | 9 | .darkmode-div { 10 | cursor: pointer; 11 | text-align: right; 12 | } 13 | 14 | @media (max-width: 992px) { 15 | .darkmode-div { 16 | text-align: right; 17 | } 18 | .main-col-footer { 19 | margin-bottom: 20px; 20 | } 21 | } 22 | 23 | @media (max-width: 575px) { 24 | .darkmode-div { 25 | text-align: left; 26 | align-self: flex-start; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /frontend/src/app/shared/hero/hero.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
Failed to load hero
5 |
6 | 7 |
8 |
9 | -------------------------------------------------------------------------------- /frontend/src/app/shared/hero/hero.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/app/shared/hero/hero.component.scss -------------------------------------------------------------------------------- /frontend/src/app/shared/image-upload-modal/image-upload-modal.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /frontend/src/app/shared/image-upload-modal/image-upload-modal.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/app/shared/image-upload-modal/image-upload-modal.component.scss -------------------------------------------------------------------------------- /frontend/src/app/shared/image-upload-modal/image-upload-modal.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from "@angular/core"; 2 | import { MatDialogRef } from "@angular/material/dialog"; 3 | 4 | @Component({ 5 | selector: "app-image-upload-modal", 6 | templateUrl: "./image-upload-modal.component.html", 7 | styleUrls: ["./image-upload-modal.component.scss"] 8 | }) 9 | export class ImageUploadModalComponent { 10 | public constructor(public dialogRef: MatDialogRef) {} 11 | 12 | public onFileSelect(event: any): void { 13 | this.dialogRef.close(event.target.files[0]); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /frontend/src/app/shared/input/input.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../styles/variables.scss"; 2 | -------------------------------------------------------------------------------- /frontend/src/app/shared/markdown-editor/markdown-editor.component.html: -------------------------------------------------------------------------------- 1 |
2 | 8 |
9 | -------------------------------------------------------------------------------- /frontend/src/app/shared/package-and-collection/catalogs-response.ts: -------------------------------------------------------------------------------- 1 | import { Catalog } from "src/generated/graphql"; 2 | 3 | export interface CatalogsResponse { 4 | catalogs?: Catalog[]; 5 | hasMore?: boolean; 6 | errors?: string[]; 7 | shouldResetCatalogs?: boolean; 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/app/shared/package-and-collection/collections-response.ts: -------------------------------------------------------------------------------- 1 | import { Collection } from "src/generated/graphql"; 2 | 3 | export interface CollectionsResponse { 4 | collections?: Collection[]; 5 | hasMore?: boolean; 6 | errors?: string[]; 7 | shouldResetCollection?: boolean; 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/app/shared/package-and-collection/limit-and-offset.ts: -------------------------------------------------------------------------------- 1 | export interface LimitAndOffset { 2 | limit: number; 3 | offset: number; 4 | } 5 | -------------------------------------------------------------------------------- /frontend/src/app/shared/package-and-collection/packages-response.ts: -------------------------------------------------------------------------------- 1 | import { Package } from "src/generated/graphql"; 2 | 3 | export interface PackagesResponse { 4 | packages?: Package[]; 5 | hasMore?: boolean; 6 | errors?: string[]; 7 | shouldResetCollection?: boolean; 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/app/shared/package-and-collection/search-parameters.ts: -------------------------------------------------------------------------------- 1 | import { LimitAndOffset } from "./limit-and-offset"; 2 | 3 | export interface SearchParameters extends LimitAndOffset { 4 | query: string; 5 | } 6 | -------------------------------------------------------------------------------- /frontend/src/app/shared/package-autocomplete/package-autocomplete.component.scss: -------------------------------------------------------------------------------- 1 | .mat-option { 2 | height: 75px; 3 | padding: 5px 10px; 4 | line-height: 75px; 5 | 6 | ::ng-deep.avatar { 7 | line-height: 20px; 8 | margin-right: 10px; 9 | } 10 | } -------------------------------------------------------------------------------- /frontend/src/app/shared/pipes/entries.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from "@angular/core"; 2 | 3 | @Pipe({ 4 | name: "entries" 5 | }) 6 | export class EntriesPipe implements PipeTransform { 7 | transform(value: any): {key: string, value: any}[] { 8 | return Object.entries(value).map(([key, value]) => ({key, value})); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/app/shared/pipes/input-error.pipe.spec.ts: -------------------------------------------------------------------------------- 1 | import { InputErrorPipe } from "./input-error.pipe"; 2 | 3 | describe("InputErrorPipe", () => { 4 | it("create an instance", () => { 5 | const pipe = new InputErrorPipe(); 6 | expect(pipe).toBeTruthy(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /frontend/src/app/shared/pipes/keys.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from "@angular/core"; 2 | 3 | @Pipe({ 4 | name: "keys" 5 | }) 6 | export class KeysPipe implements PipeTransform { 7 | transform(value: any): any[] { 8 | return Object.keys(value); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/app/shared/pipes/percent.pipe.spec.ts: -------------------------------------------------------------------------------- 1 | import { PercentPipe } from "./percent.pipe"; 2 | 3 | describe("PercentPipe", () => { 4 | it("create an instance", () => { 5 | const pipe = new PercentPipe(); 6 | expect(pipe).toBeTruthy(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /frontend/src/app/shared/pipes/percent.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from "@angular/core"; 2 | 3 | @Pipe({ 4 | name: "percent" 5 | }) 6 | export class PercentPipe implements PipeTransform { 7 | transform(value: number): string { 8 | return (value * 100).toFixed(2).replace(/\.?0+$/, "") + "%"; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/app/shared/pipes/sanitize-with-style.pipe.ts: -------------------------------------------------------------------------------- 1 | 2 | import { Pipe, PipeTransform } from "@angular/core"; 3 | import { SafeHtml, DomSanitizer } from "@angular/platform-browser"; 4 | import DOMPurify from "dompurify"; 5 | 6 | @Pipe({ 7 | name: 8 | 'sanitizeWithStyle' 9 | }) 10 | export class SanitizeWithStylePipe implements PipeTransform 11 | { 12 | constructor (private sanitizer : DomSanitizer) {} 13 | transform(html: string) : SafeHtml { 14 | // Allowing CSS is still not recommended 15 | return this.sanitizer.bypassSecurityTrustHtml( 16 | DOMPurify.sanitize(html, {ADD_ATTR: ['style']}) 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /frontend/src/app/shared/pipes/time-ago.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from "@angular/core"; 2 | 3 | import { distanceInWordsToNow } from "date-fns"; 4 | 5 | @Pipe({ 6 | name: "timeAgo" 7 | }) 8 | export class TimeAgoPipe implements PipeTransform { 9 | transform(value: Date, ..._args: any[]): string { 10 | return distanceInWordsToNow(value, { addSuffix: true, includeSeconds: false }); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /frontend/src/app/shared/pipes/truncate.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | 3 | @Pipe({ 4 | name: 'truncate' 5 | }) 6 | export class TruncatePipe implements PipeTransform { 7 | 8 | transform(text: string, length: number = 20, suffix: string = '...'): string { 9 | 10 | if (text.length > length) { 11 | let truncated: string = text.substring(0, length).trim() + suffix; 12 | return truncated; 13 | } 14 | 15 | return text; 16 | } 17 | } -------------------------------------------------------------------------------- /frontend/src/app/shared/pipes/username.pipe.spec.ts: -------------------------------------------------------------------------------- 1 | import { UsernamePipe } from "./username.pipe"; 2 | 3 | describe("UsernamePipe", () => { 4 | it("create an instance", () => { 5 | const pipe = new UsernamePipe(); 6 | expect(pipe).toBeTruthy(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /frontend/src/app/shared/pipes/username.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from "@angular/core"; 2 | import { User } from "src/generated/graphql"; 3 | 4 | @Pipe({ 5 | name: "username" 6 | }) 7 | export class UsernamePipe implements PipeTransform { 8 | transform(user: User): string { 9 | if (!user) { 10 | return ""; 11 | } 12 | 13 | if (user.firstName) { 14 | return `${this.trim(user.firstName)} ${this.trim(user.lastName)}`.trim(); 15 | } 16 | 17 | return user.username; 18 | } 19 | 20 | private trim(str: string) { 21 | return (str || "").trim(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /frontend/src/app/shared/pipes/values.pipe.spec.ts: -------------------------------------------------------------------------------- 1 | import { ValuesPipe } from "./values.pipe"; 2 | 3 | describe("ValuesPipe", () => { 4 | it("create an instance", () => { 5 | const pipe = new ValuesPipe(); 6 | expect(pipe).toBeTruthy(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /frontend/src/app/shared/pipes/values.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from "@angular/core"; 2 | 3 | @Pipe({ 4 | name: "values" 5 | }) 6 | export class ValuesPipe implements PipeTransform { 7 | transform(value: any): any[] { 8 | return Object.values(value); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/app/shared/user-details/few-packages-alert/few-packages-alert.component.html: -------------------------------------------------------------------------------- 1 |
Too Few Packages
2 |
3 | There are too few items in your collection. Collections need to have at least 2 packages to become public. 4 |
5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /frontend/src/app/shared/user-details/few-packages-alert/few-packages-alert.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/app/shared/user-details/few-packages-alert/few-packages-alert.component.scss -------------------------------------------------------------------------------- /frontend/src/app/shared/user-details/few-packages-alert/few-packages-alert.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from "@angular/core"; 2 | 3 | @Component({ 4 | selector: "app-few-packages-alert", 5 | templateUrl: "./few-packages-alert.component.html", 6 | styleUrls: ["./few-packages-alert.component.scss"] 7 | }) 8 | export class FewPackagesAlertComponent implements OnInit { 9 | constructor() {} 10 | 11 | ngOnInit(): void {} 12 | } 13 | -------------------------------------------------------------------------------- /frontend/src/app/shared/user-details/simple-create/simple-create.component.scss: -------------------------------------------------------------------------------- 1 | app-input ::ng-deep input { 2 | height: 35px; 3 | padding-top: 0; 4 | padding-bottom: 0; 5 | } 6 | -------------------------------------------------------------------------------- /frontend/src/app/shared/user-details/user-following/user-following.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../../styles/variables"; 2 | @import "../../../../styles/colors"; 3 | 4 | #user-following { 5 | .panel-div { 6 | margin-top: 30px; 7 | } 8 | 9 | .font-16 { 10 | margin-bottom: 6px; 11 | font-size: ($title-font - 4); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/app/shared/user-details/user-groups/user-groups.component.scss: -------------------------------------------------------------------------------- 1 | @import "../../../../styles/variables"; 2 | @import "../../../../styles/colors"; 3 | 4 | #user-following { 5 | .panel-div { 6 | margin-top: 30px; 7 | } 8 | 9 | .font-16 { 10 | margin-bottom: 6px; 11 | font-size: ($title-font - 4); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/app/shared/user-details/user-packages/user-packages.component.scss: -------------------------------------------------------------------------------- 1 | .loading-container { 2 | display: flex; 3 | justify-content: center; 4 | padding: 20px 0 40px; 5 | width: 100%; 6 | } 7 | 8 | .big-div-package { 9 | margin-top: 30px; 10 | } 11 | 12 | @media (max-width: 576px) { 13 | .big-div-package { 14 | margin-top: 15px; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/app/shared/user-invite-input/chip-data.ts: -------------------------------------------------------------------------------- 1 | import { ChipState } from "./chip-state"; 2 | 3 | export interface ChipData { 4 | state: ChipState; 5 | usernameOrEmailAddress?: string; 6 | stateMessage?: string; 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/app/shared/user-invite-input/chip-state.ts: -------------------------------------------------------------------------------- 1 | export enum ChipState { 2 | SUCCESS, 3 | WARNING, 4 | ERROR 5 | } 6 | -------------------------------------------------------------------------------- /frontend/src/app/ui.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from "@angular/core"; 2 | import { CommonModule } from "@angular/common"; 3 | import { UiStyleToggleService } from "./services/ui-style-toggle.service"; 4 | 5 | export function themeFactory(themeService: UiStyleToggleService) { 6 | return () => themeService.setThemeOnStart(); 7 | } 8 | 9 | @NgModule({ 10 | declarations: [], 11 | imports: [CommonModule], 12 | providers: [UiStyleToggleService] 13 | }) 14 | export class UiModule {} 15 | -------------------------------------------------------------------------------- /frontend/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/.gitkeep -------------------------------------------------------------------------------- /frontend/src/assets/dpm-logo-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/dpm-logo-180x180.png -------------------------------------------------------------------------------- /frontend/src/assets/dpm-logo-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/dpm-logo-192x192.png -------------------------------------------------------------------------------- /frontend/src/assets/dpm-logo-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/dpm-logo-256x256.png -------------------------------------------------------------------------------- /frontend/src/assets/dpm-logo-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/dpm-logo-512x512.png -------------------------------------------------------------------------------- /frontend/src/assets/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/favicon-16x16.png -------------------------------------------------------------------------------- /frontend/src/assets/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/favicon-32x32.png -------------------------------------------------------------------------------- /frontend/src/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/favicon.ico -------------------------------------------------------------------------------- /frontend/src/assets/images/card-img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/card-img.png -------------------------------------------------------------------------------- /frontend/src/assets/images/cover-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/cover-image.jpg -------------------------------------------------------------------------------- /frontend/src/assets/images/cover-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/cover-image.png -------------------------------------------------------------------------------- /frontend/src/assets/images/envelope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/envelope.png -------------------------------------------------------------------------------- /frontend/src/assets/images/galaxy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/galaxy.jpg -------------------------------------------------------------------------------- /frontend/src/assets/images/galaxy1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/galaxy1.png -------------------------------------------------------------------------------- /frontend/src/assets/images/galaxy2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/galaxy2.jpg -------------------------------------------------------------------------------- /frontend/src/assets/images/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/github.png -------------------------------------------------------------------------------- /frontend/src/assets/images/google-glass-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/google-glass-logo.png -------------------------------------------------------------------------------- /frontend/src/assets/images/link-45.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frontend/src/assets/images/location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/location.png -------------------------------------------------------------------------------- /frontend/src/assets/images/sources/raw_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/sources/raw_file.png -------------------------------------------------------------------------------- /frontend/src/assets/images/sources/redshift.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/src/assets/images/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/twitter.png -------------------------------------------------------------------------------- /frontend/src/assets/images/user-female.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/user-female.jpg -------------------------------------------------------------------------------- /frontend/src/assets/images/user-female.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/user-female.png -------------------------------------------------------------------------------- /frontend/src/assets/images/user-male.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/user-male.jpg -------------------------------------------------------------------------------- /frontend/src/assets/images/user-male2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/assets/images/user-male2.png -------------------------------------------------------------------------------- /frontend/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /frontend/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/big-armor/datapm/29c90a79182ba6113b0c70aaddcaf11703051c13/frontend/src/favicon.ico -------------------------------------------------------------------------------- /frontend/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from "@angular/core"; 2 | import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"; 3 | 4 | import { AppModule } from "./app/app.module"; 5 | import { environment } from "./environments/environment"; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch((err) => console.error(err)); 14 | -------------------------------------------------------------------------------- /frontend/src/styles/_theme.scss: -------------------------------------------------------------------------------- 1 | @import "../styles/colors"; 2 | 3 | .theme-light { 4 | @each $name, $color in $colors { 5 | #{$name}: nth($color, 1); 6 | } 7 | } 8 | 9 | .theme-dark { 10 | @each $name, $color in $colors { 11 | #{$name}: nth($color, 2); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /frontend/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.base.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [], 7 | "experimentalDecorators": true 8 | }, 9 | "files": ["src/main.ts", "src/polyfills.ts"], 10 | "include": ["src/**/*.d.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /frontend/tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "downlevelIteration": true, 9 | "experimentalDecorators": true, 10 | "moduleResolution": "node", 11 | "importHelpers": true, 12 | "target": "es2016", 13 | "module": "es2020", 14 | "lib": ["es2018", "dom", "esnext.asynciterable"], 15 | "allowSyntheticDefaultImports": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* 2 | This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience. 3 | It is not intended to be used to perform a compilation. 4 | 5 | To learn more about this file see: https://angular.io/config/solution-tsconfig. 6 | */ 7 | { 8 | "files": [], 9 | "references": [ 10 | { 11 | "path": "./tsconfig.app.json" 12 | }, 13 | { 14 | "path": "./tsconfig.spec.json" 15 | } 16 | ], 17 | "angularCompilerOptions": { 18 | "strictTemplates": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /frontend/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.base.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": ["jasmine"] 7 | }, 8 | "files": ["src/test.ts", "src/polyfills.ts"], 9 | "include": ["src/**/*.spec.ts", "src/**/*.d.ts"], 10 | "angularCompilerOptions": { 11 | "strictTemplates": true 12 | } 13 | } -------------------------------------------------------------------------------- /frontend/typescript-typedefs.js: -------------------------------------------------------------------------------- 1 | const { printSchema } = require("graphql"); 2 | /* This file is used by graphql-codegen to add typeDefs to the generated file, so that it can be used at GraphqlModule insantiation time */ 3 | module.exports = { 4 | plugin: (schema, documents, config) => { 5 | return [ 6 | // 'import gql from "graphql-tag";', This is already imported 7 | "", 8 | "export const typeDefs = gql`", 9 | printSchema(schema), 10 | "`;", 11 | "" 12 | ].join("\n"); 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /lib/LICENSE: -------------------------------------------------------------------------------- 1 | datapm-lib by Travis Collins is licensed under CC BY-ND 4.0 CC 2 | 3 | For more information, see https://datapm.io/terms -------------------------------------------------------------------------------- /lib/README.md: -------------------------------------------------------------------------------- 1 | # Data Package Manager Library (datapm-lib) 2 | 3 | [DataPM.io](https://datapm.io) is a free, open-source, and easy-to-use data management platform. Use DataPM to quickly create accurate data catalogs, publish high quality data sets, and ETL data into your production systems. 4 | 5 | This folder contains a NodeJS library that defines the GraphQL Schema for the backend server, and commonly used NodeJS classes for both the backend and client. 6 | -------------------------------------------------------------------------------- /lib/graphql-documents/AcceptInvite.graphql: -------------------------------------------------------------------------------- 1 | mutation AcceptInvite($token: String!, $username: String!, $password: String!) { 2 | acceptInvite(token: $token, username: $username, password: $password) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/AddOrUpdateGroupToPackage.graphql: -------------------------------------------------------------------------------- 1 | mutation AddOrUpdateGroupToPackage( 2 | $groupSlug: String! 3 | $packageIdentifier: PackageIdentifierInput! 4 | $permissions: [Permission!]! 5 | ) { 6 | addOrUpdateGroupToPackage(groupSlug: $groupSlug, packageIdentifier: $packageIdentifier, permissions: $permissions) { 7 | group { 8 | slug 9 | name 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/graphql-documents/AddOrUpdateUserToGroup.graphql: -------------------------------------------------------------------------------- 1 | mutation AddOrUpdateUserToGroup($groupSlug: String!, $userPermissions: [SetUserGroupPermissionsInput!]!) { 2 | addOrUpdateUserToGroup(groupSlug: $groupSlug, userPermissions: $userPermissions) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/AdminDeleteGroup.graphql: -------------------------------------------------------------------------------- 1 | mutation AdminDeleteGroup($groupSlug: String!) { 2 | adminDeleteGroup(groupSlug: $groupSlug) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/AdminDeleteUser.graphql: -------------------------------------------------------------------------------- 1 | mutation AdminDeleteUser($usernameOrEmailAddress: String!) { 2 | adminDeleteUser(usernameOrEmailAddress: $usernameOrEmailAddress) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/AdminSearchUsers.graphql: -------------------------------------------------------------------------------- 1 | query AdminSearchUsers($value: String!, $limit: Int!, $offset: Int!) { 2 | adminSearchUsers(value: $value, limit: $limit, offSet: $offset) { 3 | users { 4 | username 5 | firstName 6 | lastName 7 | emailAddress 8 | displayName 9 | status 10 | isAdmin 11 | } 12 | hasMore 13 | count 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/graphql-documents/AdminSetUserStatus.graphql: -------------------------------------------------------------------------------- 1 | mutation AdminSetUserStatus($username: String!, $status: UserStatus!, $message: String) { 2 | adminSetUserStatus(username: $username, status: $status, message: $message) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/Catalog.graphql: -------------------------------------------------------------------------------- 1 | query GetCatalog($identifier: CatalogIdentifierInput!) { 2 | catalog(identifier: $identifier) { 3 | identifier { 4 | registryURL 5 | catalogSlug 6 | } 7 | displayName 8 | description 9 | website 10 | myPermissions 11 | isPublic 12 | unclaimed 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/graphql-documents/CatalogFollowers.graphql: -------------------------------------------------------------------------------- 1 | query CatalogFollowers($identifier: CatalogIdentifierInput!, $limit: Int!, $offset: Int!) { 2 | catalogFollowers(identifier: $identifier, limit: $limit, offset: $offset) { 3 | followers { 4 | firstName 5 | lastName 6 | username 7 | displayName 8 | } 9 | hasMore 10 | count 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/graphql-documents/CatalogFollowersCount.graphql: -------------------------------------------------------------------------------- 1 | query CatalogFollowersCount($identifier: CatalogIdentifierInput!) { 2 | catalogFollowersCount(identifier: $identifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/CatalogPackages.graphql: -------------------------------------------------------------------------------- 1 | query CatalogPackages($identifier: CatalogIdentifierInput!, $offset: Int!, $limit: Int!) { 2 | catalogPackages(identifier: $identifier, offset: $offset, limit: $limit) { 3 | displayName 4 | description 5 | createdAt 6 | updatedAt 7 | isPublic 8 | myPermissions 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /lib/graphql-documents/CollectionFollowers.graphql: -------------------------------------------------------------------------------- 1 | query CollectionFollowers($identifier: CollectionIdentifierInput!, $limit: Int!, $offset: Int!) { 2 | collectionFollowers(identifier: $identifier, limit: $limit, offset: $offset) { 3 | followers { 4 | firstName 5 | lastName 6 | username 7 | displayName 8 | } 9 | hasMore 10 | count 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/graphql-documents/CollectionFollowersCount.graphql: -------------------------------------------------------------------------------- 1 | query CollectionFollowersCount($identifier: CollectionIdentifierInput!) { 2 | collectionFollowersCount(identifier: $identifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/CollectionSlugAvailable.graphql: -------------------------------------------------------------------------------- 1 | query CollectionSlugAvailable($collectionSlug: String!) { 2 | collectionSlugAvailable(collectionSlug: $collectionSlug) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/CreateAPIKey.graphql: -------------------------------------------------------------------------------- 1 | mutation CreateAPIKey($value: CreateAPIKeyInput!) { 2 | createAPIKey(value: $value) { 3 | secret 4 | label 5 | scopes 6 | id 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /lib/graphql-documents/CreateCatalog.graphql: -------------------------------------------------------------------------------- 1 | mutation CreateCatalog($value: CreateCatalogInput!) { 2 | createCatalog(value: $value) { 3 | identifier { 4 | catalogSlug 5 | } 6 | myPermissions 7 | displayName 8 | description 9 | website 10 | isPublic 11 | unclaimed 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lib/graphql-documents/CreateFollow.graphql: -------------------------------------------------------------------------------- 1 | mutation SaveFollow($follow: SaveFollowInput!) { 2 | saveFollow(follow: $follow) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/CreateGroup.graphql: -------------------------------------------------------------------------------- 1 | mutation CreateGroup($groupSlug: String!, $name: String!, $description: String!) { 2 | createGroup(groupSlug: $groupSlug, name: $name, description: $description) { 3 | slug 4 | name 5 | description 6 | createdAt 7 | creator { 8 | username 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /lib/graphql-documents/CreateMe.graphql: -------------------------------------------------------------------------------- 1 | mutation CreateMe($value: CreateUserInput!) { 2 | createMe(value: $value) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/CreatePackage.graphql: -------------------------------------------------------------------------------- 1 | mutation CreatePackage($value: CreatePackageInput!) { 2 | createPackage(value: $value) { 3 | identifier { 4 | catalogSlug 5 | packageSlug 6 | } 7 | catalog { 8 | myPermissions 9 | displayName 10 | } 11 | displayName 12 | description 13 | latestVersion { 14 | identifier { 15 | versionMajor 16 | versionMinor 17 | versionPatch 18 | } 19 | packageFile 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/graphql-documents/CreatePackageIssue.graphql: -------------------------------------------------------------------------------- 1 | mutation CreatePackageIssue($packageIdentifier: PackageIdentifierInput!, $issue: CreatePackageIssueInput!) { 2 | createPackageIssue(packageIdentifier: $packageIdentifier, issue: $issue) { 3 | issueNumber 4 | subject 5 | content 6 | status 7 | author { 8 | firstName 9 | lastName 10 | username 11 | displayName 12 | } 13 | createdAt 14 | updatedAt 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeleteAPIKey.graphql: -------------------------------------------------------------------------------- 1 | mutation DeleteAPIKey($id: String!) { 2 | deleteAPIKey(id: $id) { 3 | label 4 | scopes 5 | id 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeleteAllMyFollows.graphql: -------------------------------------------------------------------------------- 1 | mutation DeleteAllMyFollows { 2 | deleteAllMyFollows 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeleteCatalog.graphql: -------------------------------------------------------------------------------- 1 | mutation DeleteCatalog($identifier: CatalogIdentifierInput!) { 2 | deleteCatalog(identifier: $identifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeleteCatalogAvatarImage.graphql: -------------------------------------------------------------------------------- 1 | mutation DeleteCatalogAvatarImage($identifier: CatalogIdentifierInput!) { 2 | deleteCatalogAvatarImage(identifier: $identifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeleteCollection.graphql: -------------------------------------------------------------------------------- 1 | mutation DeleteCollection($identifier: CollectionIdentifierInput!) { 2 | deleteCollection(identifier: $identifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeleteCredential.graphql: -------------------------------------------------------------------------------- 1 | mutation DeleteCredential( 2 | $identifier: PackageIdentifierInput! 3 | $connectorType: String! 4 | $repositoryIdentifier: String! 5 | $credentialIdentifier: String! 6 | ) { 7 | deleteCredential( 8 | identifier: $identifier 9 | connectorType: $connectorType 10 | repositoryIdentifier: $repositoryIdentifier 11 | credentialIdentifier: $credentialIdentifier 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeleteFollow.graphql: -------------------------------------------------------------------------------- 1 | mutation DeleteFollow($follow: FollowIdentifierInput!) { 2 | deleteFollow(follow: $follow) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeleteGroup.graphql: -------------------------------------------------------------------------------- 1 | mutation DeleteGroup($groupSlug: String!) { 2 | deleteGroup(groupSlug: $groupSlug) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeleteMe.graphql: -------------------------------------------------------------------------------- 1 | mutation DeleteMe { 2 | deleteMe 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeletePackage.graphql: -------------------------------------------------------------------------------- 1 | mutation DeletePackage($identifier: PackageIdentifierInput!) { 2 | deletePackage(identifier: $identifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeletePackageIssue.graphql: -------------------------------------------------------------------------------- 1 | mutation DeletePackageIssue( 2 | $packageIdentifier: PackageIdentifierInput! 3 | $packageIssueIdentifier: PackageIssueIdentifierInput! 4 | ) { 5 | deletePackageIssue(packageIdentifier: $packageIdentifier, packageIssueIdentifier: $packageIssueIdentifier) 6 | } 7 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeletePackageIssueComment.graphql: -------------------------------------------------------------------------------- 1 | mutation DeletePackageIssueComment( 2 | $packageIdentifier: PackageIdentifierInput! 3 | $issueIdentifier: PackageIssueIdentifierInput! 4 | $issueCommentIdentifier: PackageIssueCommentIdentifierInput! 5 | ) { 6 | deletePackageIssueComment( 7 | packageIdentifier: $packageIdentifier 8 | issueIdentifier: $issueIdentifier 9 | issueCommentIdentifier: $issueCommentIdentifier 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeletePackageIssues.graphql: -------------------------------------------------------------------------------- 1 | mutation DeletePackageIssues( 2 | $packageIdentifier: PackageIdentifierInput! 3 | $issuesIdentifiers: [PackageIssueIdentifierInput!]! 4 | ) { 5 | deletePackageIssues(packageIdentifier: $packageIdentifier, issuesIdentifiers: $issuesIdentifiers) 6 | } 7 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeleteRepository.graphql: -------------------------------------------------------------------------------- 1 | mutation DeleteRepository( 2 | $identifier: PackageIdentifierInput! 3 | $connectorType: String! 4 | $repositoryIdentifier: String! 5 | ) { 6 | deleteRepository( 7 | identifier: $identifier 8 | connectorType: $connectorType 9 | repositoryIdentifier: $repositoryIdentifier 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeleteUserCatalogPermissions.graphql: -------------------------------------------------------------------------------- 1 | mutation DeleteUserCatalogPermissions($usernameOrEmailAddress: String!, $identifier: CatalogIdentifierInput!) { 2 | deleteUserCatalogPermissions(usernameOrEmailAddress: $usernameOrEmailAddress, identifier: $identifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeleteUserCollectionPermissions.graphql: -------------------------------------------------------------------------------- 1 | mutation DeleteUserCollectionPermissions($identifier: CollectionIdentifierInput!, $usernameOrEmailAddress: String!) { 2 | deleteUserCollectionPermissions(identifier: $identifier, usernameOrEmailAddress: $usernameOrEmailAddress) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/DeleteVersion.graphql: -------------------------------------------------------------------------------- 1 | mutation DeleteVersion($identifier: VersionIdentifierInput!) { 2 | deleteVersion(identifier: $identifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/EmailAddressAvailable.graphql: -------------------------------------------------------------------------------- 1 | query EmailAddressAvailable($emailAddress: String!) { 2 | emailAddressAvailable(emailAddress: $emailAddress) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/ForgotMyPassword.graphql: -------------------------------------------------------------------------------- 1 | mutation ForgotMyPassword($emailAddress: String!) { 2 | forgotMyPassword(emailAddress: $emailAddress) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/GetFollow.graphql: -------------------------------------------------------------------------------- 1 | query GetFollow($follow: FollowIdentifierInput!) { 2 | getFollow(follow: $follow) { 3 | notificationFrequency 4 | eventTypes 5 | changeType 6 | followAllPackages 7 | followAllPackageIssues 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lib/graphql-documents/GroupsByCatalog.graphql: -------------------------------------------------------------------------------- 1 | query GroupsByCatalog($catalogIdentifier: CatalogIdentifierInput!) { 2 | groupsByCatalog(catalogIdentifier: $catalogIdentifier) { 3 | group { 4 | name 5 | description 6 | slug 7 | users { 8 | user { 9 | username 10 | firstName 11 | lastName 12 | nameIsPublic 13 | displayName 14 | } 15 | permissions 16 | } 17 | } 18 | permissions 19 | packagePermissions 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/graphql-documents/GroupsByCollection.graphql: -------------------------------------------------------------------------------- 1 | query GroupsByCollection($collectionIdentifier: CollectionIdentifierInput!) { 2 | groupsByCollection(collectionIdentifier: $collectionIdentifier) { 3 | group { 4 | name 5 | slug 6 | description 7 | users { 8 | user { 9 | username 10 | firstName 11 | lastName 12 | nameIsPublic 13 | displayName 14 | } 15 | permissions 16 | } 17 | } 18 | permissions 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/graphql-documents/GroupsByPackage.graphql: -------------------------------------------------------------------------------- 1 | query GroupsByPackage($packageIdentifier: PackageIdentifierInput!) { 2 | groupsByPackage(packageIdentifier: $packageIdentifier) { 3 | group { 4 | name 5 | slug 6 | description 7 | users { 8 | user { 9 | username 10 | firstName 11 | lastName 12 | nameIsPublic 13 | displayName 14 | } 15 | permissions 16 | } 17 | } 18 | permissions 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/graphql-documents/LatestCollections.graphql: -------------------------------------------------------------------------------- 1 | query GetLatestCollections($offset: Int!, $limit: Int!) { 2 | latestCollections(offset: $offset, limit: $limit) { 3 | collections { 4 | identifier { 5 | collectionSlug 6 | } 7 | name 8 | description 9 | isPublic 10 | isRecommended 11 | } 12 | hasMore 13 | count 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/graphql-documents/ListConnectors.graphql: -------------------------------------------------------------------------------- 1 | query ListConnectors { 2 | listConnectors { 3 | connectorType 4 | displayName 5 | hasSource 6 | hasSink 7 | } 8 | } -------------------------------------------------------------------------------- /lib/graphql-documents/Login.graphql: -------------------------------------------------------------------------------- 1 | mutation Login($username: String!, $password: String!) { 2 | login(username: $username, password: $password) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/Logout.graphql: -------------------------------------------------------------------------------- 1 | mutation Logout($username: String!, $password: String!) { 2 | logout 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/Me.graphql: -------------------------------------------------------------------------------- 1 | query Me { 2 | me { 3 | isAdmin 4 | user { 5 | emailAddress 6 | displayName 7 | firstName 8 | lastName 9 | username 10 | description 11 | location 12 | twitterHandle 13 | gitHubHandle 14 | website 15 | nameIsPublic 16 | locationIsPublic 17 | twitterHandleIsPublic 18 | gitHubHandleIsPublic 19 | emailAddressIsPublic 20 | websiteIsPublic 21 | uiDarkModeEnabled 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/graphql-documents/MovePackage.graphql: -------------------------------------------------------------------------------- 1 | mutation MovePackage($identifier: PackageIdentifierInput!, $catalogIdentifier: CatalogIdentifierInput!) { 2 | movePackage(identifier: $identifier, catalogIdentifier: $catalogIdentifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/MyAPIKeys.graphql: -------------------------------------------------------------------------------- 1 | query MyAPIKeys { 2 | myAPIKeys { 3 | id 4 | label 5 | scopes 6 | createdAt 7 | lastUsed 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lib/graphql-documents/MyCatalogs.graphql: -------------------------------------------------------------------------------- 1 | query MyCatalogs { 2 | myCatalogs { 3 | identifier { 4 | registryURL 5 | catalogSlug 6 | } 7 | displayName 8 | description 9 | website 10 | isPublic 11 | unclaimed 12 | myPermissions 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/graphql-documents/MyGroups.graphql: -------------------------------------------------------------------------------- 1 | query MyGroups { 2 | myGroups { 3 | slug 4 | name 5 | description 6 | myPermissions 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /lib/graphql-documents/MyRecentlyViewedCollections.graphql: -------------------------------------------------------------------------------- 1 | query MyRecentlyViewedCollections($offset: Int!, $limit: Int!) { 2 | myRecentlyViewedCollections(offset: $offset, limit: $limit) { 3 | logs { 4 | targetCollection { 5 | identifier { 6 | collectionSlug 7 | } 8 | name 9 | description 10 | isPublic 11 | isRecommended 12 | } 13 | } 14 | hasMore 15 | count 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/graphql-documents/PackageFetched.graphql: -------------------------------------------------------------------------------- 1 | mutation PackageFetched($identifier: VersionIdentifierInput!) { 2 | packageFetched(identifier: $identifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/PackageFollowers.graphql: -------------------------------------------------------------------------------- 1 | query PackageFollowers($identifier: PackageIdentifierInput!, $limit: Int!, $offset: Int!) { 2 | packageFollowers(identifier: $identifier, limit: $limit, offset: $offset) { 3 | followers { 4 | firstName 5 | lastName 6 | username 7 | displayName 8 | } 9 | hasMore 10 | count 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/graphql-documents/PackageFollowersCount.graphql: -------------------------------------------------------------------------------- 1 | query PackageFollowersCount($identifier: PackageIdentifierInput!) { 2 | packageFollowersCount(identifier: $identifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/PackageIssue.graphql: -------------------------------------------------------------------------------- 1 | query PackageIssue($packageIdentifier: PackageIdentifierInput!, $packageIssueIdentifier: PackageIssueIdentifierInput!) { 2 | packageIssue(packageIdentifier: $packageIdentifier, packageIssueIdentifier: $packageIssueIdentifier) { 3 | issueNumber 4 | subject 5 | content 6 | author { 7 | firstName 8 | lastName 9 | username 10 | displayName 11 | } 12 | status 13 | createdAt 14 | updatedAt 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/graphql-documents/PackageIssueFollowers.graphql: -------------------------------------------------------------------------------- 1 | query PackageIssueFollowers( 2 | $identifier: PackageIdentifierInput! 3 | $issueIdentifier: PackageIssueIdentifierInput! 4 | $limit: Int! 5 | $offset: Int! 6 | ) { 7 | packageIssueFollowers(identifier: $identifier, issueIdentifier: $issueIdentifier, limit: $limit, offset: $offset) { 8 | followers { 9 | firstName 10 | lastName 11 | username 12 | displayName 13 | } 14 | hasMore 15 | count 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/graphql-documents/PackageIssueFollowersCount.graphql: -------------------------------------------------------------------------------- 1 | query PackageIssueFollowersCount($identifier: PackageIdentifierInput!, $issueIdentifier: PackageIssueIdentifierInput!) { 2 | packageIssueFollowersCount(identifier: $identifier, issueIdentifier: $issueIdentifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/PackageVersionsDiff.graphql: -------------------------------------------------------------------------------- 1 | query PackageVersionsDiff($newVersion: VersionIdentifierInput!, $oldVersion: VersionIdentifierInput!) { 2 | packageVersionsDiff(newVersion: $newVersion, oldVersion: $oldVersion) { 3 | newVersion { 4 | versionMajor 5 | versionMinor 6 | versionPatch 7 | } 8 | oldVersion { 9 | versionMajor 10 | versionMinor 11 | versionPatch 12 | } 13 | differences { 14 | type 15 | pointer 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/graphql-documents/PackageVersionsDiffs.graphql: -------------------------------------------------------------------------------- 1 | query PackageVersionsDiffs($packageIdentifier: PackageIdentifierInput!, $offset: Int!, $limit: Int!) { 2 | packageVersionsDiffs(packageIdentifier: $packageIdentifier, offset: $offset, limit: $limit) { 3 | newVersion { 4 | versionMajor 5 | versionMinor 6 | versionPatch 7 | } 8 | oldVersion { 9 | versionMajor 10 | versionMinor 11 | versionPatch 12 | } 13 | differences { 14 | type 15 | pointer 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/graphql-documents/PlatformSettings.graphql: -------------------------------------------------------------------------------- 1 | query PlatformSettings { 2 | platformSettings { 3 | key 4 | isPublic 5 | serializedSettings 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /lib/graphql-documents/PublicPlatformSettingsByKey.graphql: -------------------------------------------------------------------------------- 1 | query PublicPlatformSettingsByKey($key: String!) { 2 | publicPlatformSettingsByKey(key: $key) { 3 | serializedSettings 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /lib/graphql-documents/RecoverMyPassword.graphql: -------------------------------------------------------------------------------- 1 | mutation RecoverMyPassword($value: RecoverMyPasswordInput!) { 2 | recoverMyPassword(value: $value) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/RegistryStatus.graphql: -------------------------------------------------------------------------------- 1 | query RegistryStatus { 2 | registryStatus { 3 | status 4 | version 5 | registryUrl 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /lib/graphql-documents/RemoveGroupFromCatalog.graphql: -------------------------------------------------------------------------------- 1 | mutation RemoveGroupFromCatalog($groupSlug: String!, $catalogIdentifier: CatalogIdentifierInput!) { 2 | removeGroupFromCatalog(groupSlug: $groupSlug, catalogIdentifier: $catalogIdentifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/RemoveGroupFromCollection.graphql: -------------------------------------------------------------------------------- 1 | mutation RemoveGroupFromCollection($groupSlug: String!, $collectionIdentifier: CollectionIdentifierInput!) { 2 | removeGroupFromCollection(groupSlug: $groupSlug, collectionIdentifier: $collectionIdentifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/RemoveGroupFromPackage.graphql: -------------------------------------------------------------------------------- 1 | mutation RemoveGroupFromPackage($groupSlug: String!, $packageIdentifier: PackageIdentifierInput!) { 2 | removeGroupFromPackage(groupSlug: $groupSlug, packageIdentifier: $packageIdentifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/RemovePackageFromCollection.graphql: -------------------------------------------------------------------------------- 1 | mutation RemovePackageFromCollection( 2 | $collectionIdentifier: CollectionIdentifierInput! 3 | $packageIdentifier: PackageIdentifierInput! 4 | ) { 5 | removePackageFromCollection(collectionIdentifier: $collectionIdentifier, packageIdentifier: $packageIdentifier) 6 | } 7 | -------------------------------------------------------------------------------- /lib/graphql-documents/RemovePackagePermissions.graphql: -------------------------------------------------------------------------------- 1 | mutation RemovePackagePermissions($usernameOrEmailAddress: String!, $identifier: PackageIdentifierInput!) { 2 | removePackagePermissions(usernameOrEmailAddress: $usernameOrEmailAddress, identifier: $identifier) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/RemoveUserFromGroup.graphql: -------------------------------------------------------------------------------- 1 | mutation RemoveUserFromGroup($username: String!, $groupSlug: String!) { 2 | removeUserFromGroup(username: $username, groupSlug: $groupSlug) { 3 | slug 4 | name 5 | users { 6 | user { 7 | username 8 | firstName 9 | lastName 10 | nameIsPublic 11 | displayName 12 | } 13 | permissions 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/graphql-documents/RunJob.graphql: -------------------------------------------------------------------------------- 1 | mutation RunJob($key: String!, $job: JobType!) { 2 | runJob(key: $key, job: $job) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/SavePlatformSettings.graphql: -------------------------------------------------------------------------------- 1 | mutation SavePlatformSettings($settings: PlatformSettingsInput!) { 2 | savePlatformSettings(settings: $settings) { 3 | key 4 | isPublic 5 | serializedSettings 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /lib/graphql-documents/SearchCatalogs.graphql: -------------------------------------------------------------------------------- 1 | query SearchCatalogs($query: String!, $limit: Int!, $offset: Int!) { 2 | searchCatalogs(query: $query, limit: $limit, offSet: $offset) { 3 | catalogs { 4 | identifier { 5 | catalogSlug 6 | } 7 | displayName 8 | description 9 | myPermissions 10 | } 11 | hasMore 12 | count 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/graphql-documents/SearchUsers.graphql: -------------------------------------------------------------------------------- 1 | query SearchUsers($value: String!, $limit: Int!, $offset: Int!) { 2 | searchUsers(value: $value, limit: $limit, offSet: $offset) { 3 | users { 4 | username 5 | firstName 6 | lastName 7 | displayName 8 | nameIsPublic 9 | } 10 | hasMore 11 | count 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lib/graphql-documents/SetAsAdmin.graphql: -------------------------------------------------------------------------------- 1 | mutation SetAsAdmin($username: String!, $isAdmin: Boolean!) { 2 | setAsAdmin(username: $username, isAdmin: $isAdmin) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/SetCatalogAvatarImage.graphql: -------------------------------------------------------------------------------- 1 | mutation SetCatalogAvatarImage($identifier: CatalogIdentifierInput!, $image: Base64ImageUpload!) { 2 | setCatalogAvatarImage(identifier: $identifier, image: $image) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/SetCatalogCoverImage.graphql: -------------------------------------------------------------------------------- 1 | mutation SetCatalogCoverImage($identifier: CatalogIdentifierInput!, $image: Base64ImageUpload!) { 2 | setCatalogCoverImage(identifier: $identifier, image: $image) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/SetCollectionCoverImage.graphql: -------------------------------------------------------------------------------- 1 | mutation SetCollectionCoverImage($identifier: CollectionIdentifierInput!, $image: Base64ImageUpload!) { 2 | setCollectionCoverImage(identifier: $identifier, image: $image) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/SetGroupAsAdmin.graphql: -------------------------------------------------------------------------------- 1 | mutation SetGroupAsAdmin($groupSlug: String!, $isAdmin: Boolean!) { 2 | setGroupAsAdmin(groupSlug: $groupSlug, isAdmin: $isAdmin) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/SetMyAvatarImage.graphql: -------------------------------------------------------------------------------- 1 | mutation SetMyAvatarImage($image: Base64ImageUpload!) { 2 | setMyAvatarImage(image: $image) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/SetMyCoverImage.graphql: -------------------------------------------------------------------------------- 1 | mutation SetMyCoverImage($image: Base64ImageUpload!) { 2 | setMyCoverImage(image: $image) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/SetPackageCoverImage.graphql: -------------------------------------------------------------------------------- 1 | mutation SetPackageCoverImage($identifier: PackageIdentifierInput!, $image: Base64ImageUpload!) { 2 | setPackageCoverImage(identifier: $identifier, image: $image) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/SetPackagePermissions.graphql: -------------------------------------------------------------------------------- 1 | mutation SetPackagePermissions( 2 | $identifier: PackageIdentifierInput! 3 | $value: [SetPackagePermissionInput!]! 4 | $message: String! 5 | ) { 6 | setPackagePermissions(identifier: $identifier, value: $value, message: $message) 7 | } 8 | -------------------------------------------------------------------------------- /lib/graphql-documents/SetUserCatalogPermission.graphql: -------------------------------------------------------------------------------- 1 | mutation SetUserCatalogPermission( 2 | $identifier: CatalogIdentifierInput! 3 | $value: [SetUserCatalogPermissionInput!]! 4 | $message: String! 5 | ) { 6 | setUserCatalogPermission(identifier: $identifier, value: $value, message: $message) 7 | } 8 | -------------------------------------------------------------------------------- /lib/graphql-documents/SetUserCollectionPermissions.graphql: -------------------------------------------------------------------------------- 1 | mutation SetUserCollectionPermissions( 2 | $identifier: CollectionIdentifierInput! 3 | $value: [SetUserCollectionPermissionsInput!]! 4 | $message: String! 5 | ) { 6 | setUserCollectionPermissions(identifier: $identifier, value: $value, message: $message) 7 | } 8 | -------------------------------------------------------------------------------- /lib/graphql-documents/UpdateCatalog.graphql: -------------------------------------------------------------------------------- 1 | mutation UpdateCatalog($identifier: CatalogIdentifierInput!, $value: UpdateCatalogInput!) { 2 | updateCatalog(identifier: $identifier, value: $value) { 3 | identifier { 4 | catalogSlug 5 | } 6 | displayName 7 | description 8 | myPermissions 9 | website 10 | isPublic 11 | unclaimed 12 | myPermissions 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/graphql-documents/UpdateGroup.graphql: -------------------------------------------------------------------------------- 1 | mutation UpdateGroup($groupSlug: String!, $name: String!, $description: String!) { 2 | updateGroup(groupSlug: $groupSlug, name: $name, description: $description) { 3 | slug 4 | name 5 | description 6 | myPermissions 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /lib/graphql-documents/UpdateMyPassword.graphql: -------------------------------------------------------------------------------- 1 | mutation UpdateMyPassword($value: UpdateMyPasswordInput!) { 2 | updateMyPassword(value: $value) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/UpdatePackageIssue.graphql: -------------------------------------------------------------------------------- 1 | mutation UpdatePackageIssue( 2 | $packageIdentifier: PackageIdentifierInput! 3 | $issueIdentifier: PackageIssueIdentifierInput! 4 | $issue: UpdatePackageIssueInput! 5 | ) { 6 | updatePackageIssue(packageIdentifier: $packageIdentifier, issueIdentifier: $issueIdentifier, issue: $issue) { 7 | issueNumber 8 | subject 9 | content 10 | status 11 | author { 12 | firstName 13 | lastName 14 | username 15 | displayName 16 | } 17 | createdAt 18 | updatedAt 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/graphql-documents/UpdatePackageIssuesStatuses.graphql: -------------------------------------------------------------------------------- 1 | mutation UpdatePackageIssuesStatuses( 2 | $packageIdentifier: PackageIdentifierInput! 3 | $issuesIdentifiers: [PackageIssueIdentifierInput!]! 4 | $status: UpdatePackageIssueStatusInput! 5 | ) { 6 | updatePackageIssuesStatuses( 7 | packageIdentifier: $packageIdentifier 8 | issuesIdentifiers: $issuesIdentifiers 9 | status: $status 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /lib/graphql-documents/User.graphql: -------------------------------------------------------------------------------- 1 | query User($username: String!) { 2 | user(username: $username) { 3 | emailAddress 4 | firstName 5 | lastName 6 | username 7 | displayName 8 | nameIsPublic 9 | location 10 | twitterHandle 11 | gitHubHandle 12 | website 13 | locationIsPublic 14 | twitterHandleIsPublic 15 | gitHubHandleIsPublic 16 | emailAddressIsPublic 17 | websiteIsPublic 18 | description 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/graphql-documents/UserCatalogs.graphql: -------------------------------------------------------------------------------- 1 | query UserCatalogs($username: String!, $offSet: Int!, $limit: Int!) { 2 | userCatalogs(username: $username, offSet: $offSet, limit: $limit) { 3 | catalogs { 4 | identifier { 5 | registryURL 6 | catalogSlug 7 | } 8 | displayName 9 | description 10 | website 11 | isPublic 12 | unclaimed 13 | myPermissions 14 | } 15 | hasMore 16 | count 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/graphql-documents/UserCollections.graphql: -------------------------------------------------------------------------------- 1 | query UserCollections($username: String!, $offSet: Int!, $limit: Int!) { 2 | userCollections(username: $username, offSet: $offSet, limit: $limit) { 3 | collections { 4 | identifier { 5 | collectionSlug 6 | } 7 | name 8 | description 9 | myPermissions 10 | isPublic 11 | } 12 | hasMore 13 | count 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/graphql-documents/UserFollowers.graphql: -------------------------------------------------------------------------------- 1 | query UserFollowers($username: String!, $limit: Int!, $offset: Int!) { 2 | userFollowers(username: $username, limit: $limit, offset: $offset) { 3 | followers { 4 | firstName 5 | lastName 6 | username 7 | displayName 8 | } 9 | hasMore 10 | count 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/graphql-documents/UserFollowersCount.graphql: -------------------------------------------------------------------------------- 1 | query UserFollowersCount($username: String!) { 2 | userFollowersCount(username: $username) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/UsernameAvailable.graphql: -------------------------------------------------------------------------------- 1 | query UsernameAvailable($username: String!) { 2 | usernameAvailable(username: $username) 3 | } 4 | -------------------------------------------------------------------------------- /lib/graphql-documents/UsersByCatalog.graphql: -------------------------------------------------------------------------------- 1 | query UsersByCatalog($identifier: CatalogIdentifierInput!) { 2 | usersByCatalog(identifier: $identifier) { 3 | user { 4 | username 5 | firstName 6 | lastName 7 | nameIsPublic 8 | displayName 9 | } 10 | permissions 11 | packagePermissions 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lib/graphql-documents/UsersByCollection.graphql: -------------------------------------------------------------------------------- 1 | query UsersByCollection($identifier: CollectionIdentifierInput!) { 2 | usersByCollection(identifier: $identifier) { 3 | user { 4 | username 5 | firstName 6 | lastName 7 | nameIsPublic 8 | displayName 9 | } 10 | permissions 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/graphql-documents/UsersByPackage.graphql: -------------------------------------------------------------------------------- 1 | query UsersByPackage($identifier: PackageIdentifierInput!) { 2 | usersByPackage(identifier: $identifier) { 3 | user { 4 | username 5 | firstName 6 | lastName 7 | nameIsPublic 8 | displayName 9 | } 10 | permissions 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/graphql-documents/VerifyEmailAddress.graphql: -------------------------------------------------------------------------------- 1 | mutation VerifyEmailAddress($token: String!) { 2 | verifyEmailAddress(token: $token) 3 | } 4 | -------------------------------------------------------------------------------- /lib/images-schema.gql: -------------------------------------------------------------------------------- 1 | """ 2 | Validates the uploaded base64 image 3 | """ 4 | directive @validBase64Image on ARGUMENT_DEFINITION 5 | 6 | enum IMAGE_UPLOAD_ERROR_TYPE { 7 | IMAGE_NOT_INITIALIZED 8 | IMAGE_FORMAT_NOT_SUPPORTED 9 | IMAGE_TOO_LARGE 10 | UNKNOWN 11 | } 12 | 13 | input Base64ImageUpload { 14 | base64: String! 15 | } 16 | 17 | type Image { 18 | id: String 19 | type: String! 20 | mimeType: String! 21 | } 22 | -------------------------------------------------------------------------------- /lib/prettierrc.yaml: -------------------------------------------------------------------------------- 1 | # Reference: https://prettier.io/docs/en/options.html 2 | 3 | tabWidth: 4 4 | useTabs: false 5 | printWidth: 120 6 | 7 | trailingComma: none 8 | bracketSpacing: true 9 | jsxBracketSameLine: true 10 | 11 | semi: true 12 | arrowParens: always 13 | singleQuote: false 14 | -------------------------------------------------------------------------------- /lib/src/APIKeyUtil.ts: -------------------------------------------------------------------------------- 1 | export function createAPIKeyFromParts(id: string, secret: string): string { 2 | return Buffer.from(id + "." + secret).toString("base64"); 3 | } 4 | -------------------------------------------------------------------------------- /lib/src/CountPrecisionUtil.ts: -------------------------------------------------------------------------------- 1 | import { CountPrecision } from "./PackageFile-v0.8.1"; 2 | 3 | export function leastPrecise(a: CountPrecision, b: CountPrecision): CountPrecision { 4 | if (a === CountPrecision.GREATER_THAN || b === CountPrecision.GREATER_THAN) return CountPrecision.GREATER_THAN; 5 | 6 | if (a === CountPrecision.APPROXIMATE || b === CountPrecision.APPROXIMATE) return CountPrecision.APPROXIMATE; 7 | 8 | return CountPrecision.EXACT; 9 | } 10 | -------------------------------------------------------------------------------- /lib/src/DataHandlingUtil.ts: -------------------------------------------------------------------------------- 1 | /** How updates are provided from the source */ 2 | export enum UpdateMethod { 3 | BATCH_FULL_SET = "BATCH_FULL_SET", // All records, every time 4 | APPEND_ONLY_LOG = "APPEND_ONLY_LOG", // New records are appended to the end of a stream (uses offsets) 5 | CONTINUOUS = "CONTINUOUS" // New records are appended to the the stream, and the stream should never close 6 | } 7 | -------------------------------------------------------------------------------- /lib/src/LibPackageVersionUtil.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | 3 | /** Finds the package.json for this lib */ 4 | export function libPackageVersion(): string { 5 | const dataLibPackageFile = fs.readFileSync("package.json"); 6 | const dataLibPackageJSON = JSON.parse(dataLibPackageFile.toString()); 7 | return dataLibPackageJSON.version; 8 | } 9 | -------------------------------------------------------------------------------- /lib/src/NameUtil.ts: -------------------------------------------------------------------------------- 1 | export function nameToSlug(name: string): string { 2 | const withDashes = name.toLowerCase().replace(/\W+/g, "-"); 3 | 4 | const withoutSurroundingDashes = withDashes.replace(/^[-|_]+/g, "").replace(/[-|_]+$/g, ""); 5 | 6 | const shortended = withoutSurroundingDashes.substr(0, 38); 7 | 8 | const withoutSurroundingDashes2 = shortended.replace(/^[-|_]+/g, "").replace(/[-|_]+$/g, ""); 9 | 10 | return withoutSurroundingDashes2; 11 | } 12 | -------------------------------------------------------------------------------- /lib/src/main.ts: -------------------------------------------------------------------------------- 1 | export * from "./PackageFile-v0.32.1"; 2 | export * from "./PackageUtil"; 3 | export * from "./Validators"; 4 | export * from "./CountPrecisionUtil"; 5 | export * from "./SinkState"; 6 | export * from "./TimeoutPromise"; 7 | export * from "./SocketUtil"; 8 | export * from "./DataHandlingUtil"; 9 | export * from "./APIKeyUtil"; 10 | export * from "./NameUtil"; 11 | export * from "./Parameter"; 12 | export * from "./LibPackageVersionUtil"; 13 | 14 | export * from "./DataPMVersion"; 15 | -------------------------------------------------------------------------------- /lib/src/types/base-x/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "base-x" { 2 | class BaseX { 3 | constructor(alphabet: string); 4 | encode(value: Buffer): string; 5 | decode(value: string): Buffer; 6 | } 7 | export default BaseX; 8 | } 9 | -------------------------------------------------------------------------------- /lib/test/packageFiles/congressional-legislators.LICENSE.md: -------------------------------------------------------------------------------- 1 | # Test License 2 | 3 | This is not a real license. Just a test. 4 | -------------------------------------------------------------------------------- /lib/test/packageFiles/congressional-legislators.README.md: -------------------------------------------------------------------------------- 1 | # Test README 2 | 3 | This is where a readme might go. 4 | -------------------------------------------------------------------------------- /lib/test/packageFiles/twitter-sample.LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | License not defined. Contact author. -------------------------------------------------------------------------------- /lib/test/packageFiles/twitter-sample.README.md: -------------------------------------------------------------------------------- 1 | # twitter-sample 2 | 3 | Twitter 1% streaming sample -------------------------------------------------------------------------------- /lib/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["tslint:recommended", "tslint-config-prettier"] 3 | } 4 | -------------------------------------------------------------------------------- /terraform/.gitignore: -------------------------------------------------------------------------------- 1 | secrets 2 | *.json 3 | *.p12 4 | .terraform.lock.hcl 5 | .terraform -------------------------------------------------------------------------------- /terraform/backend-example.config: -------------------------------------------------------------------------------- 1 | bucket = "" 2 | prefix = "/terraform-state" -------------------------------------------------------------------------------- /terraform/environments/production.config: -------------------------------------------------------------------------------- 1 | bucket = "datapm-production-ops" 2 | prefix = "state" 3 | -------------------------------------------------------------------------------- /terraform/environments/test.config: -------------------------------------------------------------------------------- 1 | bucket = "datapm-test-ops-v4" 2 | prefix = "state" 3 | --------------------------------------------------------------------------------