The script.src setter is distorted by Lightning Web Security (salesforce)

In below code when I tried to run/load script on Lightning web component (LWC) with Lightning Web Security (LWS) enable which throw the error on the screen “This page has an error. You might just need to refresh it. [NoErrorObjectAvailable] Script error.”
after evaluating on LWS console (salesforce) it gave me the warning like :
“The script.src setter is distorted by Lightning Web Security (salesforce)”

(function(){
    // Create a queue, but don't obliterate an existing one!
    var analytics = window.analytics = window.analytics || [];
    // If the real analytics.js is already on the page return.
    if (analytics.initialize) return;
    // If the snippet was invoked already show an error.
    if (analytics.invoked) {
      if (window.console && console.error) {
        console.error('Segment snippet included twice.');
      }
      return;
    }
    // Invoked flag, to make sure the snippet
    // is never invoked twice.
    analytics.invoked = true;
    // A list of the methods in Analytics.js to stub.
    analytics.methods = [
      'trackSubmit',
      'trackClick',
      'trackLink',
      'trackForm',
      'pageview',
      'identify',
      'reset',
      'group',
      'track',
      'ready',
      'alias',
      'debug',
      'page',
      'once',
      'off',
      'on',
      'addSourceMiddleware',
      'addIntegrationMiddleware',
      'setAnonymousId',
      'addDestinationMiddleware'
    ];
    // Define a factory to create stubs. These are placeholders
    // for methods in Analytics.js so that you never have to wait
    // for it to load to actually record data. The `method` is
    // stored as the first argument, so we can replay the data.
    analytics.factory = function(method){
      return function(){
        var args = Array.prototype.slice.call(arguments);
        args.unshift(method);
        analytics.push(args);
        return analytics;
      };
    };
    // For each of our methods, generate a queueing stub.
    for (var i = 0; i < analytics.methods.length; i++) {
      var key = analytics.methods[i];
      analytics[key] = analytics.factory(key);
    }
    // Define a method to load Analytics.js from our CDN,
    // and that will be sure to only ever load it once.
    analytics.load = function(key, options){
      // Create an async script element based on your key.    
      var script = document.createElement('script');
      script.type = 'text/javascript';
      script.async = true;    
      script.src = 'https://cdn.segment.com/analytics.js/v1/'
         + key + '/analytics.min.js';
      // Insert our script next to the first script element.
      script = 
      var first = document.getElementsByTagName('script')[0];    
      first.parentNode.insertBefore(script, first);
      analytics._loadOptions = options;
    };
    analytics._writeKey = "MDcA4pxOnFcCtsEoLjMCW5C7jyFG0C97"
    // Add a version to keep track of what's in the wild.
    analytics.SNIPPET_VERSION = '4.15.2';
    // Load Analytics.js with your key, which will automatically
    // load the tools you've enabled for your account. Boosh!
    analytics.load("MDcA4pxOnFcCtsEoLjMCW5C7jyFG0C97");
    // Make the first page call to load the integrations. If
    // you'd like to manually name or tag the page, edit or
    // move this call however you'd like.
    analytics.page();
  })();

When Overflow occurs, update background color of DIV or FORM

I have a form that requires a specific section to have a maximum height of 3 inches – due to physical printing purposes. In this section, I have a textarea for users to provide a response (with no maximum character limit). If the response is too long, it will push the next element/item in that div off the screen (i.e., overflow). When overflow occurs, I’d like either the entire FORM’s (preferably) or the overflowing DIV’s background to change color to visually indicate that overflow has occurred.

I can’t post the actual code but here is a sample that details what I’m trying to accomplish. Looking to change color of either <form>, <section id="middle">, and/or <div id="overflow" class="static-section">.

div {
  border: 1px solid #CCC;
  background-color: #FFF;
  margin-bottom: 1rem;
  padding: 1rem;
  width: 8.5in;
  max-height: 7in;
}

.static-section {
  display: grid;
  overflow: hidden;
  max-height: 3in;
  width: 7.5in;

  * {
    margin-top: .5rem;
    margin-bottom: .5rem;
    padding: .5rem;
  }
}

textarea {
  field-sizing: content;
}
<form id="entry">
  <section id="top">
    <h1>HEADER</h1>
  </section>

  <section id="middle">
    <div id="overflow" class="static-section">
      <label>This section is locked at a max 3 inches. I want the background color to be red if the anything makes this section overflow.</label>
      <textarea placeholder="type in this section until the following paragraph starts to go off the screen. this is when I want the background color to change."></textarea>
      <p>When this information starts to go off the screen (i.e., enabling overflow - which the scrollbars are being hidden by the static-section class), I want the background color of this div to change. This will provide a visual indication that the provided response is too long.</p>
    </div>
  </section>

  <section id="footer">
    <h1>FOOTER</h1>
  </section>
</form>

Any assistance with this is greatly appreciated.

I can’t parse the icon properly; it comes as an artifact from an array of objects

Come array with object

I need to parse this code into an icon because it’s currently displaying as an artifact. The project uses Blynk and Ant Design. The icon in the Tag component should be displayed correctly.The icon comes from the tags array of objects.

const TagList = ({ tags, onClose, closable, color }) => {  
useEffect(() => {
    console.log('TAGS ----', tags);   const tag = {
    color: "#fa541c",
    icon: "ue755",
    id: 6594,
    name: "test 4" };   }, [tags]);

  return (
    <ul className="search-item-info--tags-list">
      {tags?.map((tag) => (
        <li key={tag.id} className="search-item-info--tags-item">
          <Tag
            data-icon={tag.icon}
            color={color || tag.color}
            closable={closable}
            onClose={() => onClose(tag)}
          >
            {tag.icon ? tag.name : <span className="tag-name">{tag.name}</span>}
          </Tag>
        </li>
      ))}
    </ul>   ); };

TagList.propTypes = {   tags:
PropTypes.arrayOf(PropTypes.shape(TAG.shape)),   onClose:
PropTypes.func,   closable: PropTypes.bool,   color: PropTypes.string
};

Can I apply Content-Security-Policy to scripts only from our domains?

We’re running test html pages in next.js and have the following next.config.js set:

  reactStrictMode: true,
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          {
            key: 'Content-Security-Policy-Report-Only',
            value: "require-trusted-types-for 'script';",
          },
        ],
      },
    ];
  },
};

That appears to be applying the CSP rules to any file in the test page, regardless of where it came from. The whole point of the test page is to test our own code to ensure we’re CSP compliant, but on some of the test pages we’re including JS files from external sites (e.g. JWPlayer, jQuery) and if they’re not CSP compliant, we want them to be ignored in terms of needing to comply with the rules – they should get a free pass.

We thought that the above config would give us that as it’s set to report only anyway, but instead we’re seeing external scripts misbehaving. They’re not able to get their job done successfully.

Is there some syntax change in that config above that will make it apply CSP only to for example:
‘example.com,scripts.example.com,other.example.com’ and anything else is unaffected.

I’m assuming the answer will be no because the config applies to ‘the test page’ and therefore any script on that page must comply.

Angular provideAppInitializer is initialized after ngOnInit

I have in my ApplicationConfig provider

provideAppInitializer(() => {
  inject(AppConfigService)
})

In component MainPageComponent I have ngOnInit(), which geting data from backend every refresh.

 ngOnInit() {
this.loginService.getHi().subscribe({
  next: result => {
    this.text = result;
    void this._router.navigate(['mainPage'])
  },
  error: err => {
    void this._router.navigate(['login'])
    console.log("Login failed", err);
  },
  complete: () => {
    console.log('Login process completed ' + localStorage.getItem("token"));
  }
})

problem is Global app initialization is after ngOnInit() is called, how to avoid it?

AppConfigService

export class AppConfigService {
  private appConfig!: AppConfig;

  constructor(private readonly http: HttpClient) {
    void this.loadAppConfig();
  }

   loadAppConfig(): Promise<any> {
    return firstValueFrom(this.http.get<AppConfig>('/config/config.json').pipe(tap(data => {
      console.log('my data ' + JSON.stringify(data));
      this.appConfig = data;
    })));
  }

  getBackendBaseUrl(): string {
    return this.appConfig.environment.backendURL;
  }

Custom menu able to import data from a CSV file with semicolons separators [duplicate]

I would like to have a script for downloading into a sheet the values contained on a CSV file (stored on my laptop) and which using as separators semicolons.

Into Google Sheets, I would like to have a customized menu which can allow the followings things :

  • Displaying a popup window in order to select my CSV file stored somewhere into my laptop.
  • After, the script needs to get back the values contained into the selected CSV file.
  • At the end, I would like to have the values pasted into my current sheet and if possible, that the popup window be closed.

On a previous post, I found this code :

Google App Scripts side :

function onOpen() {
  SpreadsheetApp.getUi().createMenu("Import DI GMAO").addItem("Choisir un fichier CSV sur mon ordinateur ...", "importCsv").addToUi();

}

function importCsv(e){
  if (!e) {
    SpreadsheetApp.getUi().showModalDialog(HtmlService.createHtmlOutputFromFile("index"), "Téléchargement d'un fichier DI GMAO");
    return;
  }
  const csv = Utilities.parseCsv(Utilities.newBlob(...e).getDataAsString());
    
  //Browser.msgBox(csv);
  const sheet = SpreadsheetApp.getActiveSheet();
  sheet.getRange(1, 1, csv.length, csv[0].length).setValues(csv);
}

HTML side :

<form>
  <input type="file" name="file" onchange="importCsv(this.parentNode)" accept=".csv,text/csv">
  <div id="progress">Attente ...</div>
</form>
<script>
function importCsv(e) {
  const div = document.getElementById("progress");
  div.innerHTML = "Téléchargement en cours ...";
  const file = e.file.files[0];
  const f = new FileReader();
  f.onload = d => google.script.run.withSuccessHandler(_ => {
    div.innerHTML = "Téléchargement terminé !";
    setTimeout(google.script.host.close, 1000);
  }).importCsv([[...new Int8Array(d.target.result)], file.type, file.name]);
  f.readAsArrayBuffer(file);
}
</script>

This code works perfectly only if my CSV file have as separators commas (,).
If the CSV file have as separators semicolons (;), and that’s my case, the script doesn’t works and I didn’t understand why.

Google Apps Script – Custom menu able to import data from a CSV file with semicolons separators

I would like to have a script for downloading into a sheet the values contained on a CSV file (stored on my laptop) and which using as separators semicolons.

Into Google Sheets, I would like to have a customized menu which can allow the followings things :

  • Displaying a popup window in order to select my CSV file stored somewhere into my laptop.
  • After, the script needs to get back the values contained into the selected CSV file.
  • At the end, I would like to have the values pasted into my current sheet and if possible, that the popup window be closed.

On a previous post, I found this code :

Google App Scripts side :

function onOpen() {
  SpreadsheetApp.getUi().createMenu("Import DI GMAO").addItem("Choisir un fichier CSV sur mon ordinateur ...", "importCsv").addToUi();

}

function importCsv(e){
  if (!e) {
    SpreadsheetApp.getUi().showModalDialog(HtmlService.createHtmlOutputFromFile("index"), "Téléchargement d'un fichier DI GMAO");
    return;
  }
  const csv = Utilities.parseCsv(Utilities.newBlob(...e).getDataAsString());
    
  //Browser.msgBox(csv);
  const sheet = SpreadsheetApp.getActiveSheet();
  sheet.getRange(1, 1, csv.length, csv[0].length).setValues(csv);
}

HTML side :

<form>
  <input type="file" name="file" onchange="importCsv(this.parentNode)" accept=".csv,text/csv">
  <div id="progress">Attente ...</div>
</form>
<script>
function importCsv(e) {
  const div = document.getElementById("progress");
  div.innerHTML = "Téléchargement en cours ...";
  const file = e.file.files[0];
  const f = new FileReader();
  f.onload = d => google.script.run.withSuccessHandler(_ => {
    div.innerHTML = "Téléchargement terminé !";
    setTimeout(google.script.host.close, 1000);
  }).importCsv([[...new Int8Array(d.target.result)], file.type, file.name]);
  f.readAsArrayBuffer(file);
}
</script>

This code works perfectly only if my CSV file have as separators commas (,).
If the CSV file have as separators semicolons (;), and that’s my case, the script doesn’t works and I didn’t understand why.

Does anyone have any idea? Thank you in advance for your help.

django form submit is not sending all fields in the form when the fields are populated through javascript

When i fill out the form manually, it posts all 7 fields correctly. However, if the form is auto populated through js, the post request is only sending 2 out of the 7 fields (previous_package_description and comments). The script seems to be populating the fields correctly on the form, but they are just not being sent. Any help would be appreciated, thanks in advance

package.html

<form action="{% url 'add_supplier_package' supplier_id=supplier_id supplier_ingredient_supplypoint_id=supplier_ingredient_supplypoint.pk %}" method="POST" class="form" enctype="multipart/form-data">
                {% csrf_token %}
        
                <!-- Group 1: Previous Package Description -->
                <fieldset id="group-1">
                    <legend>Previous Package Description</legend>
                    <div class="form-row">
                        {{ form.previous_package_description.label_tag }}
                        {{ form.previous_package_description }}
                    </div>
                </fieldset>
        
                <!-- Group 2: Package Details -->
                <fieldset id="package-details-group">
                    <legend>Add New Packsize</legend>
        
                    <div class="form-row">
                        {% for field in form %}
                            {% if field.name != "package_sizes" and field.name != "supplier_ingredient_supplypoint" and field.name != "package_description" and field.name != "previous_package_description" %}
                                <div class="form-item">
                                    {{ field.label_tag }}
                                    {{ field }}
                                </div>
                            {% endif %}
                        {% endfor %}
                    </div>
        
                    <!-- Package Sizes Section -->
                    <div class="form-row">
                        <label for="package_sizes">Package Sizes:</label>
                        <div id="package_sizes_list">
                            <!-- Dynamic package size inputs will appear here -->
                        </div>
                        <button type="button" id="addPackageSizeButton" style="width: 20%;"class="btn" onclick="addPackageSize()">Add Package Size</button>
                    </div>
        
                    <!-- Auto-filled Package Description -->
                    <div class="form-row">
                        <label for="package_description">Package Description:</label>
                        <input type="text" id="package_description" name="package_description" readonly>
                    </div>
        
                    <!-- Hidden field to store package sizes -->
                    {{ form.package_sizes }}

                    <input type="hidden" name="supplier_ingredient_supplypoint" value="{{ supplier_ingredient_supplypoint.supplier_ingredient_supplypoint_id }}">
                </fieldset>
        
                <!-- Submit and Cancel Buttons -->
                <div class="form-button">
                    <button type="submit" class="btn" onclick="return confirm('Confirm Submit?')"><span>Submit</span></button>
                    <button type="button" class="btn cancel" onclick="history.back()"><span>Close</span></button>
                </div>
            </form>

form.py

class SupplierPackageForm(forms.ModelForm):
    previous_package_description = forms.ModelChoiceField(
        queryset=PackageHeader.objects.all(),  
        label="Previous Package Description",
        required=False,  
        empty_label="-- Select Existing Packsize --",
    )
    package_description = forms.CharField(
        max_length=200,
        label="Package Description (auto-filled)",
        required=False,
        widget=forms.TextInput(attrs={'readonly': 'readonly'})
    )
    package_type = forms.ChoiceField(
        choices=[
            (None, "-- None --"),
            ("IBC", "IBC"),
            ("PK", "Prepack"),
            ("DRUM", "DRUM"),  
            ("PAIL","PAIL"),
            ("BULK","BULK")
        ],
        label="Package Type",
        required=False,
        widget=forms.Select(attrs={"placeholder": "Select Package Type"})
    )
    uom = forms.ModelChoiceField(
        queryset=PackageUOM.objects.all(),
        label="Unit of Measurement",
        required=True,
        to_field_name='uom',
        empty_label="-- Select UOM --",
    )
    package_sizes = forms.CharField(
        widget=forms.HiddenInput(),
        required=False
    )
    supplier_ingredient_supplypoint = forms.ModelChoiceField(
        queryset=SupplierIngredientSupplyPoint.objects.all(),
        required=True,
        widget=forms.HiddenInput()
    )
    comments = forms.CharField(
        max_length=200,
        label="Comments",
        required=False,
        widget=forms.Textarea(attrs={"placeholder": "Enter comments here", "rows": 3, "cols": 40})
    )

    class Meta:
        model = SupplierPackage  # Connect the form to the SupplierPackage model
        fields = ['previous_package_description', 'package_description', 'package_type', 'uom','package_sizes', 'supplier_ingredient_supplypoint', 'comments']

    def __init__(self, *args, **kwargs):
        supplier_ingredient_supplypoint = kwargs.pop('supplier_ingredient_supplypoint', None)
        super().__init__(*args, **kwargs)

        if supplier_ingredient_supplypoint:
            self.initial['supplier_ingredient_supplypoint'] = supplier_ingredient_supplypoint
            self.fields['supplier_ingredient_supplypoint'].queryset = SupplierIngredientSupplyPoint.objects.filter(
                pk=supplier_ingredient_supplypoint.pk
            )

        self.fields['previous_package_description'].queryset = PackageHeader.objects.all()
        self.fields['previous_package_description'].choices = [("", "-- Add New Packsize --")] + [
            (package.package_id, f"{package.package_description} ({package.comments or ''})")
            for package in PackageHeader.objects.all()
        ]
        self.initial['previous_package_description'] = ""

js function

document.addEventListener('DOMContentLoaded', function () {
                const previousDescriptionField = document.querySelector('[name="previous_package_description"]');
                const packageDetailsGroup = document.getElementById('package-details-group');
                const packageDescriptionField = document.getElementById('package_description');
                const uomField = document.getElementById('id_uom');
                const packageTypeField = document.getElementById('id_package_type');
                const packageSizesList = document.getElementById('package_sizes_list');

                function toggleGroupState() {
                    if (previousDescriptionField.value) {
                        packageDetailsGroup.style.backgroundColor = '#e0e0e0';
                        packageDetailsGroup.querySelectorAll('input, select, button').forEach(input => {
                            input.setAttribute('readonly', true);
                            input.setAttribute('disabled', true);
                        });

                        // Fetch data and populate fields
                        fetch(`${getPackageDetailsUrl}?package_id=${previousDescriptionField.value}`)
                            .then(response => response.json())
                            .then(data => {
                                console.log('Returned data:', data);
                                if (!data.error) {
                                    uomField.value = data.uom;
                                    packageTypeField.value = data.package_type;

                                    packageDescriptionField.value = data.package_description;

                                    // Populate the comments field
                                    const commentsField = document.getElementById("id_comments");
                                    if (commentsField) {
                                        commentsField.value = data.comments || "";  // Ensure it's not null
                                    }

                                    // Clear existing package sizes and add new ones
                                    packageSizesList.innerHTML = '';

                                    if ( !!data.package_sizes ) {
                                        data.package_sizes.split(',').forEach(size => {
                                            const sizeInput = document.createElement('input');
                                            sizeInput.type = 'text';
                                            sizeInput.value = size.trim();
                                            sizeInput.setAttribute('readonly', true);
                                            sizeInput.classList.add('package-size-input');
                                            packageSizesList.appendChild(sizeInput);
                                        });
                                    }
                                }
                            })
                            .catch(error => {
                                console.error('Error fetching package details:', error);
                            });
                    } else {
                        packageDetailsGroup.style.backgroundColor = '';
                        packageDetailsGroup.querySelectorAll('input, select, button').forEach(input => {
                            input.removeAttribute('readonly');
                            input.removeAttribute('disabled');
                        });

                        packageDescriptionField.value = '';
                        packageSizesList.innerHTML = '';
                    }
                }

                previousDescriptionField.addEventListener('change', toggleGroupState);
                $('#id_previous_package_description').on('select2:select', toggleGroupState);
            });

Fastest way to process audio segments and concatenate buffers in Node.js

I am trying to optimize the performance of a Node.js function that generates audio segments (for example something like OpenAIs TTS API) and then concatenates the resulting audio buffers. My goal is to speed up the reading of each audio response into the buffer and the final concatenation of audio buffers.

Current Approach

Naively I thought that it would be as simple as calling all of the audio segments, then reading them all into their own buffer and putting them together. Here is a simplified version of what I am doing now:

const createAudioSegment = async ([i, segment]) => {
    const response = await openai.audio.speech.create({
        model: "tts-1",
        voice: "echo",
        input: text,
    });
    return response;
};

const audio_texts = ["text 1", "text 2"] // list of text to turn into audio

// Process dialogue segments in parallel
const audioSegments = await Promise.all(
    audio_texts.map((text) => createAudioSegment(text))
);


const audioBuffers = await Promise.all(
    audioSegments.map(async (segment) => {
        const arrayBuffer = await segment.arrayBuffer();
        return Buffer.from(arrayBuffer);
    })
);

const finalBuffer = Buffer.concat(audioBuffers);

Performance Issues

Overall, the time it takes to do this is usually 40-60 seconds. However, when logging the individual operations, I noticed that it is really the reading of each audio segment into its individual buffer that takes the majority of the time. As an example, for a scenario with 12 audio segments, I would expect to see the following timing:

  • Total Audio Segment Time: 2333 ms
  • Audio Buffer Total Read Time: 27455 ms
  • Audio Buffer Individual Read Times (ms): [1035,3420,6497,96,150,360,70,88,20344,32,83,254]
  • Buffer Concatenation Time: 2 ms

Question

What could be causing such a large discrepancy between the individual read times? Is this something that is avoidable with a more efficient way to do this?

Form disable the overflow

I try to implement an overflow in Form react-router, that’s work in a classic <div></div> but when I use <Form></Form> my overflow` stop to work. I don’t find any topic who talk about that.

The context is a Remix app who use import { Form } from 'react-router' the version of React route is the V7`

example work

<div>
 <div style={{overflowY: "auto"}}>
   <div>Truc</div>
   <div>Truc</div>
   .../...
   <div>Truc</div>
 </div>
</div>

example don’t work

<Form>
 <div style={{overflowY: "auto"}}>
   <div>Truc</div>
   <div>Truc</div>
   .../...
   <div>Truc</div>
 </div>
</Form>

is it a Bug or Formcannot work with the overflow or there is a trick for this case ? Because all the other style work except the overflow

Using Path Aliasing on NPM package

I am in the processes of developing an NPM package with many different directories. Internally, I manage this by using subpath imports in the package.json.

“imports” : { “#*”: “./src”, “#factories”: “./src/factories”…}

This works well when isolated to the package. However, when I install the package on a consuming application, the consuming application takes issue with the alaising when importing and using the package.

Is there a way to keep the path alaising isolated to the package and not have to transfer additional configuration to the consuming application, or do I need to just return to the uglier but functional unaliased relative paths?

Safari throwing alert when checking if an app Scheme/URL is valid

I am using the following code to check if a mobile app exists on the users phone, if it does then open app, if not then redirect to app store. It works clean on Android, but on Safari simply just checking if the Scheme/URL exists pops up a Safari cannot open the page because the address is invalid

  function checkReadyState() {
    if (reader.readyState === 4) {
      //check to see whether request for the file failed or succeeded
      if ((reader.status == 200) || (reader.status == 0)) {
        //page exists -- redirect to the url
        console.log(mobile+ " : does exist") ;
        document.location.href = mobile ;
      } else {
        //if the url does not exist
        console.log(mobile+ " : does NOT exist") ;
        goToStore() ;
      }
    }
    
  }// end of checkReadyState()
     
  console.log("Redirect to App or to Store") ;
  var mobile = "myapp://path/to/resource" ; 
  var reader = new XMLHttpRequest();
  reader.open('get', mobile, true);
                
  //check each time the ready state changes
  //to see if the object is ready
  reader.onreadystatechange = checkReadyState;
    
  // Sends the request for the file data to the server
  // Use null for "get" mode
  reader.send(null);    

I added all this because simply doing a window.location = mobile triggered the same Alert message. I thought this would do things behind the scene and not alert the user interrupting the UI flow.

How can I fix this or what other method can I use to simply check if an app/scheme exists without triggering an alert on the users phone?

How to properly handle errors in Nest.js service layer

We are building an API using Nest.js and MikroORM and we are having a debate on several things related to the service “layer” of Nest.js.

Let’s suppose you have the following update method on a service.

This method does several things:

  • Firsts, asks to the ORM if the project exists. If thats not the case it returns a NotFoundError

  • Second, it checks if the client exists. If that’s not the case, the service returns a NotFoundError.

  • Finally, proceeds with the update

async update(
  id: number,
  updateProjectDto: UpdateProjectDto,
): Promise<Projects> {
  try {
    const project = await this.projectRepository.findOneOrFail(id);
    if (updateProjectDto.client_id) {
      project.client = await this.clientService.findOne(
        updateProjectDto.client_id,
      );
    }

    this.projectRepository.assign(project, updateProjectDto);
    await this.projectRepository.getEntityManager().flush();
    return project;
  } catch (error) {
    this.logger.error('Error updating project', error);
    throw error;
  }
}

Here’s our findOne in clients

async findOne(id: number) {
  try {
    return await this.clientsRepository.findOneOrFail({ id });
  } catch (error) {
    this.logger.error(`Error finding client`, error);
    throw error;
  }
}

Our questions are the following:

  • When should we wrap our business logic inside a try catch?

  • Should we use try catch for every method on our API or let the errors bubble up, as we are not doing anything in particular with them?

  • Should the service throw HTTPExceptions (taking into account its not the “proper” layer to do that). We think it’s ok to throw them here for simplicity but who knows.

Thanks in advance!

Performance implications of using complex objects as default parameter

I want to use a very complicated object as a default parameter. For example, in prisma ORM, you can wrap multiple db calls in a transaction:

this.prisma.$transaction(async (tx) => {
  await tx.table1.create()
  await tx.table2.create()
}

These inner db calls can be complicated, so I may want helper functions for them. However, the helper functions can be called from many places and may or may not be used inside a transaction. To solve this, I optionally pass the transaction, and use it if it exists:

// My function with a complex default param
async createModelIfNotExists(name, color, prisma = this.prisma) {
  return await prisma.upsert({...})
}

...

// Call from within transaction, and use transaction's prisma client:
this.prisma.$transaction(async (tx) => {
  this.createModelIfNotExists("new model 1", "blue", tx)
  ...
})

// Call on its own, and it will use the prisma object attached to "this"
this.createModelIfNotExists("new model 2", "green")

Note that tx is a very large & complex object. It manages the db connection and keeps track of all my models.

My question is – is there a performance overhead to doing this? If I was writing Python, there would be, because Python tries to be smart & initializes the default parameter even if you don’t use the function. If I wrote it like Python, the function signature would look like this:

// The default param is now instantiated in the function
async createModelIfNotExists(name, color, prisma = null) {
  prisma = prisma ?? this.prisma
  return await prisma.upsert({...})
}

I am concerned about the potential overhead of instantiating this object even when it’s not used.

I tried Googling this, but have only seen results for more basic JS objects that the programmer writes themselves.

Alternatively, if you have suggestions on how to test the performance of this, I could do that instead.