Development Guidelines

Development Guidelines

This development guide is provided for contributors to assess any MR submitted for approval meets the minimum criteria for a review. It is a requirement to adhere to this guide’s rules and guidance, failure to meet this Guide will not result in an MergeRequest being accepted.

Eslint Rules

To enforce consistency across the platform, all Eslint rules must be adhered to in order for the project to build. In order to streamline the development process across contributions, and reduce feedback cycles regarding MR’s the platform will be adding explicit ESLINT rules to automate potential bugs and pitfalls regarding code-formatting.

For a reference regarding Eslint enforced rules kindly refer to: .eslintrc.js.

DataModeling Guide

When contributing a feature that expand on the existing schema, the DataModelingGuide must be followed, in addition to the Graphql rules segment below.

Scoping Guide

To enforce access controls, all Queries, Mutations, and Model Fields should be marked with the @Authorized decorator and given relevant scopes that should have access to them. MRs that add queries, mutations, or fields without @Authorized will be rejected.

The currently available generic scopes are:

  • root: Grant access to the root scope to give all 1P clients access.

  • thirdParty: Grant access to the thirdParty scope to give all 3P clients access.

  • anonymous: Grant access to the anonymous scope to give all anonymous callers access.

For more sensitive data such as RED data, unique scopes should be created and used. An existing example of this is the restricted:profileName scope, which limits access to the profile name field of a Profile.

Graphql Guide

Gql - Perfer Connections over Arrays

When adding an array connecting two Entity types, always use a Connection. Connections allow for the adoption of pagination, and augmenting metadata between the two entities specific to the relationship (Edge), or across the collection (Connection).

❌ Don’t:

@ObjectType
Foo {
    @Field([Bar])
    relatedBar: Bar[]
}

✅ Do:

@ObjectType
Foo {
    @Field(BarConnection)
    relatedBar: BarConnection
}

Gql - Prefer Args over InputType

Graphql queries by default take in args in a destructured format. Encapsulating an entire argument list in an InputType is redundant and adds a potential layer of complexity for a client.

❌ Don’t:

@InputType
FooInputType {
    @Field()
    limit: number;
}

✅ Do:

@ArgsType
FooArgs {
    @Field()
    limit: number;
}

Gql - Prefer @Args over @Arg

Graphql arguments should be supplied inline. Encapsulating an entire argument list in an Arg('option') is redundant and adds a potential layer of complexity for a client.

❌ Don’t:

    async plays(@Arg('options') { filter, timeRange }: PlaysOptions, @Ctx() ctx: ApolloContext):

✅ Do:

    async plays(@Args() { filter, timeRange }: PlaysOptions, @Ctx() ctx: ApolloContext):

Implementing DataAccessObjects

DataAccessObjects (Daos) are intenteded to be used as a light abstraction layer between Firefly and one of it’s service dependancies. The DAO serves two functions: DataRetrieval, DataProcessing via the usage of a Transformer.

Input parameters must be provided as a singular object

Input parameters passed from a resolver to a Dao should be passed via Object construction, and destructured to extract the relevant fields.

❌ Don’t:

// ArtistDao.ts

    async getArtist(
        musicTerritory: string,
        id: string,
        caTokenMap: CloudAuthTokenMap,
        cachePolicy: CachePolicy,
    ): Promise<Artist> {

✅ Do:

// ArtistDao.ts
    interface GetArtistRequest extends DaoRequest {
        id: string;
    }
    async getArtist({ context, id }: GetArtistRequest): Promise<Artist> {

All Input objects into a DAO’s function should be interfaced and extended off DaoRequest

❌ Don’t:

// ArtistDao.ts
    interface GetArtistRequest {
        id: string;
    }

✅ Do:

// ArtistDao.ts
    interface GetArtistRequest extends DaoRequest {
        id: string;
    }

Breaking Changes Communication and Versioning

Communication Protocol for Breaking Changes

To ensure that all stakeholders are informed of any breaking changes, we will implement a standardized communication protocol that includes:

Notification Process: Notifications will be sent to the entire impacted project team via Slack channels and email groups. This ensures that everyone is aware of the changes, regardless of their specific team.

Major Version Update Process

To maintain clarity and version control within our Firefly package, the following versioning rule will be enforced:

Major Updates: Prefix commits with “breaking:” to trigger a major version bump (e.g., from 0.1.0 to 1.0.0).